接受在解组 JSON 时动态键的 proto 结构

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

Accept dynamic keys in proto struct when unmarshalling JSON

问题

我的Proto文件大致如下:

  1. message Test {
  2. Service services = 1;
  3. }
  4. message Service {
  5. map<string, ServiceData> services = 1;
  6. }
  7. message ServiceData {
  8. string command = 1;
  9. string root = 2;
  10. }

这个.proto文件可以支持以下这样的JSON结构:

  1. {
  2. "services": {
  3. "service1": {
  4. "command": "command1",
  5. "root": "/"
  6. },
  7. "service2": {
  8. "command": "command2",
  9. "root": "/"
  10. }
  11. }
  12. }

现在,我想要读取test.json文件并进行解组:

  1. var test Test
  2. err := json.Unmarshal([]byte(file), &test)

为了成功解组这个JSON,你需要对.proto文件进行以下更改:

  1. message Test {
  2. map<string, ServiceData> services = 1;
  3. }
  4. message ServiceData {
  5. string command = 1;
  6. string root = 2;
  7. }

这样,你就可以成功解组这个JSON了。

英文:

My Proto file looks something like this:

  1. message Test {
  2. Service services = 1;
  3. }
  4. message Service {
  5. string command = 1;
  6. string root = 2;
  7. }

This .proto can support a json like this:

  1. {
  2. &quot;services&quot;: {
  3. &quot;command&quot;: &quot;command2&quot;,
  4. &quot;root&quot;: &quot;/&quot;
  5. },
  6. }

But, I want to manage a json that looks like this:

  1. {
  2. &quot;services&quot;: {
  3. &quot;service1&quot;: {
  4. &quot;command&quot;: &quot;command1&quot;,
  5. &quot;root&quot;: &quot;/&quot;
  6. },
  7. &quot;service2&quot;: {
  8. &quot;command&quot;: &quot;command2&quot;,
  9. &quot;root&quot;: &quot;/&quot;
  10. },
  11. },
  12. }

So, here all the services will have common structure but the key name will vary (i.e. &quot;service1&quot;, &quot;service2&quot;)

Now, I want to read the data from test.json and unmarshal it:

  1. var test *Test
  2. err := json.Unmarshal([]byte(file), &amp;test)

What changes should I do in the .proto so that I can unmarshall this json successfully?

答案1

得分: 2

使用 proto map

  1. message Test {
  2. map<string, Service> services = 1;
  3. }
  4. message Service {
  5. string command = 1;
  6. string root = 2;
  7. }

proto map 在 Go 中被编译为 map[K]V,所以在这种情况下是 map[string]*Service,这是建议的用于建模具有任意键的 JSON 的方式。

这将产生以下输出:

  1. services:{key:"service1" value:{command:"command1" root:"/"}} services:{key:"service2" value:{command:"command2" root:"/"}}

示例程序:

  1. package main
  2. import (
  3. "encoding/json"
  4. "example.com/pb"
  5. "fmt"
  6. )
  7. const file = `{
  8. "services": {
  9. "service1": {
  10. "command": "command1",
  11. "root": "/"
  12. },
  13. "service2": {
  14. "command": "command2",
  15. "root": "/"
  16. }
  17. }
  18. }
  19. `
  20. func main() {
  21. test := &pb.Test{}
  22. err := json.Unmarshal([]byte(file), test)
  23. if err != nil {
  24. panic(err)
  25. }
  26. fmt.Println(test)
  27. }
英文:

Use a proto map:

  1. message Test {
  2. map&lt;string, Service&gt; services = 1;
  3. }
  4. message Service {
  5. string command = 1;
  6. string root = 2;
  7. }

The proto map is compiled to map[K]V in Go, so map[string]*Service in this case, which is the recommended way to model JSON with arbitrary keys.

This will give the following output:

  1. services:{key:&quot;service1&quot; value:{command:&quot;command1&quot; root:&quot;/&quot;}} services:{key:&quot;service2&quot; value:{command:&quot;command2&quot; root:&quot;/&quot;}}

Example program:

  1. package main
  2. import (
  3. &quot;encoding/json&quot;
  4. &quot;example.com/pb&quot;
  5. &quot;fmt&quot;
  6. )
  7. const file = `{
  8. &quot;services&quot;: {
  9. &quot;service1&quot;: {
  10. &quot;command&quot;: &quot;command1&quot;,
  11. &quot;root&quot;: &quot;/&quot;
  12. },
  13. &quot;service2&quot;: {
  14. &quot;command&quot;: &quot;command2&quot;,
  15. &quot;root&quot;: &quot;/&quot;
  16. }
  17. }
  18. }
  19. `
  20. func main() {
  21. test := &amp;pb.Test{}
  22. err := json.Unmarshal([]byte(file), test)
  23. if err != nil {
  24. panic(err)
  25. }
  26. fmt.Println(test)
  27. }

huangapple
  • 本文由 发表于 2021年11月24日 15:29:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/70092138.html
匿名

发表评论

匿名网友

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

确定