We're using proto3 and trying to write a proto message to generate a golang structure which can be marshaled as a JSON output with a particular structure.
The data needs to have nested arrays of mixed types (specifically, the vCard format as specified here)
The problem we're running into is generating an array with mixed types. For example, just "vcardArray:["vcard",100] that is, an array with a string and an int32
If we use Oneof
as so:
message Vcard {
oneof vcard {
string name = 1;
int32 value = 2;
}
}
We can generate something like:
[
{"name":"vcard"},
{"int":100}
]
If we use Any as so:
message VcardArray {
repeated google.protobuf.Any vcard = 1;
}
We can generate:
[
{
type: "type.googleapis.com/google.protobuf.StringValue",
value: "vcard"
},
{
type: "type.googleapis.com/google.protobuf.Int32Value",
value: 100
},
]
We expect the next JSON:
"vcardArray": [
"vcard",
[
[ "version", {},"text","4.0"],
[ "tel", {
"pref":"1",
"type":[
"work",
"voice"
]
}
],
[...],
[...]
]
]
The central question, is it possible to generate arrays of of mixed elements such as ["vcard",[...]] and if so, how can it be done?
There's two parts of your question:
The answer to your first question is that you can use an array of interface{}
, which means basically an array of untyped values.
type Person struct {
First string `json:"first_name"`
Aliases []interface{} `json:"aliases"`
}
https://play.golang.org/p/sZfstLQAIf2
Now, knowing what the go struct you want is, how can you specify it in proto?
The short answer is you can't. (If you're curious, you can take a look at how the *.pb.go file is generated)
However, you could write a function that takes the struct that protoc will generate for you and translate it into your own struct. That means you'll have to keep it up to date as you need to add or remove fields. This also means that protoc can continue to use it's structs independently then how you might need to generate json.