MffnMn
MffnMn

Reputation: 420

Specifying the JSON name for protobuf extension

I've added an extending message to a message and need to marshal it as a json. However the field name for the extension message is [message.extension_message_name].

I would prefer it to be named just extension_message_name, without the braces and prefix, since this extension message exists elsewhere in our API and and having this weird name adds confusion.

As far as I can tell the bit of code responsible is in protobuf/jsonpb, where the JSONName is set with fmt.Sprintf("[%s]", desc.Name and cannot be overwritten it seems.

Anyone have a workaround for this?

Upvotes: 13

Views: 14893

Answers (3)

abcalphabet
abcalphabet

Reputation: 1278

As per the language guide:

Message field names are mapped to lowerCamelCase and become JSON object keys. If the json_name field option is specified, the specified value will be used as the key instead.

So tagging your field with json_name should do the trick, for example this:

message TestMessage {
    string myField = 1 [json_name="my_special_field_name"];
}

Should make myField have the name my_special_field_name when marshalled to JSON.

Upvotes: 18

Liyan Chang
Liyan Chang

Reputation: 8051

You've got some options but that's because none of them are good:

  1. Create a new struct with different json struct tags and then use reflection to overlay one struct onto the other.

  2. Use https://github.com/favadi/protoc-go-inject-tag to inject custom struct tags, but you'll probably find that you need to use a different tag then json to avoid conflicts and then find a json library that allows for a custom struct tag

  3. Rewrite the json bytes after you marshaled it to find and replace in the stringified text.

Upvotes: 0

wgoodall01
wgoodall01

Reputation: 1878

One option would be to use Go's encoding/json package and a tagged struct to decode/marshal the json yourself, something like this:

type Example struct {
    ExtMessageName string `json:"extension_message_name"`
}

msg := Example{ExtMessageName: "This is a test"}

jsonBytes, err := json.Marshal(msg)

if err != nil {
    fmt.Printf("error: %v", err)
    return
}

fmt.Println(string(jsonBytes))

example on play.golang.org

which then outputs:

{"extension_message_name":"This is a test"}

Upvotes: -1

Related Questions