Goal
I want to save an object serialized as JSON in a gRPC message.
Info
The Microsoft documentation says to use the type google.protobuf.Value
for JSON.
The serialized object should then be converted with Value.Parser.ParseJson
.
And converted again on the other side with JsonFormatter.Default.Format
so that it can then be deserialized.
https://learn.microsoft.com/en-us/aspnet/core/grpc/protobuf?view=aspnetcore-8.0#value
Problem
It is not explained why.
If I use string
as type, I do not have to convert it with Value.Parser.ParseJson
.
Question
Is it okay if I use string
or does google.protobuf.Value
have an advantage that I don’t see?
(You can see differences in the output whether string
or google.protobuf.Value
is used.)
gRPC Message
message PingResponseMessage {
google.protobuf.Timestamp ResponseTimeUtc = 1;
string JsonString = 2;
google.protobuf.Value JsonValue = 3;
}
Create gRPC Message
Settings settings = new() {Name = "Dog", Port = 4000};
PingResponseMessage pingResponseMessage = new()
{
ResponseTimeUtc = Timestamp.FromDateTime(DateTime.UtcNow),
JsonString = JsonConvert.SerializeObject(settings),
JsonValue = Value.Parser.ParseJson(JsonConvert.SerializeObject(settings)),
};
Output
{
"ResponseTimeUtc": {
"seconds": "1711525732",
"nanos": 394125400
},
"JsonString": "{"Name":"Dog","Port":4000}",
"JsonValue": {
"struct_value": {
"fields": {
"Name": {
"string_value": "Dog"
},
"Port": {
"number_value": 4000
}
}
}
}
}
2
Answers
Using
Value
has the advantage that anyone using the structure on the other side doesn’t have to parse the JSON themselves, or worry about oddities that particular JSON formatters have (e.g. representations of infinity etc).If the other side actually wants it as JSON (e.g. to deserialize to a different representation using Json.NET or System.Text.Json) then it’s somewhat inefficient to go via
Value
. On the other hand, the other side might be happy to process it as "the same structure that is normally represented as JSON" (which is basically whatValue
is) in which case they can do so directly without any additional string parsing. (And without worrying about non-standard JSON.)This started out as a comment but getting too long, so:
I’m not sure that the documentation say what you think it says.
The way I understand it, they simply say that instead of working with the Value methods (i.e.
Value.ForStruct
,Value.ForBool
etc’), if the value is complex, it might be easier to useValue.Parser.ParseJson
and give it a json string).The example they show is for a relatively simple struct with only a couple of properties – and the code for creating and for reading it is quite long and cumbersome in comparison to the code for creating and reading its json equivalent.
That being said, I do think Jon Skeet’s answer addressed your question exactly.