指定 Protobuf 扩展的 JSON 名称

huangapple go评论89阅读模式
英文:

Specifying the JSON name for protobuf extension

问题

我已经将一个扩展消息添加到消息中,并需要将其转换为JSON。然而,扩展消息的字段名为[message.extension_message_name]

我希望它的名称只是extension_message_name,而不带有大括号和前缀,因为这个扩展消息在我们的API中的其他地方也存在,并且这个奇怪的名称会增加混淆。

据我所知,负责此操作的代码位于protobuf/jsonpb中,其中使用fmt.Sprintf("[%s]", desc.Name)设置了JSONName,并且似乎无法被覆盖。

有人有解决这个问题的方法吗?

英文:

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?

1: https://github.com/golang/protobuf/blob/master/jsonpb/jsonpb.go#L256 "jsonpb marshaller"

答案1

得分: 12

根据语言指南

消息字段名称映射为lowerCamelCase,并成为JSON对象的键。如果指定了json_name字段选项,则将使用指定的值作为键。

因此,通过使用json_name标记字段,可以解决问题,例如:

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

当编组为JSON时,myField将被命名为my_special_field_name

英文:

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.

答案2

得分: 0

你有几个选项,但这是因为它们都不是很好:

  1. 创建一个带有不同 JSON 结构标签的新结构体,然后使用反射将一个结构体覆盖到另一个结构体上。

  2. 使用 https://github.com/favadi/protoc-go-inject-tag 来注入自定义的结构体标签,但你可能会发现需要使用一个不同的标签来避免冲突,然后找一个允许自定义结构体标签的 JSON 库。

  3. 在将其编组为字符串后,重写 JSON 字节,以查找和替换字符串化的文本中的内容。

英文:

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.

答案3

得分: -1

一种选择是使用Go的encoding/json包和带有标签的结构体来自己解码/编组JSON,类似于以下代码:

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))

在play.golang.org上的示例

运行以上代码将输出:

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

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"}

huangapple
  • 本文由 发表于 2016年11月5日 01:34:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/40428691.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定