Marshall / Unmarshal JSONPB

时间:2018-04-05 13:15:51

标签: go proto

我正在尝试将一些json数据解组为原型消息。

  

JSON

   {
        "id": 1,
        "first_name": "name",
        "phone_numbers": []
    }
  

message Item {
  uint32 id=1;
  string name=2;
  repeated string numbers=3;
}
  

Proto.go

type Item struct {
    Id    uint32   `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
    Name   string   `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
    Numbers   []string `protobuf:"bytes,4,rep,name=numbers" json:"numbers,omitempty"`
}

如何将上面的JSON映射到我的proto消息(从我可以看到,无法在proto atm中指定标记)?

1 个答案:

答案 0 :(得分:1)

您的JSON文档与原型定义不匹配; name!= first_name和numbers!= phone_numbers。

您可以定义另一个与Item具有相同字段但不同的struct标签的类型,然后转换为Item:

    var x struct {
            Id      uint32   `json:"id,omitempty"`
            Name    string   `json:"first_name,omitempty"`
            Numbers []string `json:"phone_numbers,omitempty"`
    }

    if err := json.Unmarshal(jsonDoc, &x); err != nil {
            log.Fatal(err)
    }

    var i = Item(x)

如果要解码的每个 JSON文档都具有此结构,那么让Item实现json.Unmarshaler可能更方便:

package main

import (
        "encoding/json"
        "fmt"
        "log"
)

var jsonDoc = []byte(`
{
  "id": 1,
  "first_name": "name",
  "phone_numbers": [
    "555"
  ]
}
`)

type Item struct {
        Id      uint32   `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
        Name    string   `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
        Numbers []string `protobuf:"bytes,4,rep,name=numbers" json:"numbers,omitempty"`
}

// You can define this function is item_json.go or so, then it 
// isn't removed if you re-generate your types.
func (i *Item) UnmarshalJSON(b []byte) error {
        type item struct {
                Id      uint32   `json:"id,omitempty"`
                Name    string   `json:"first_name,omitempty"`
                Numbers []string `json:"phone_numbers,omitempty"`
        }

        var x item
        if err := json.Unmarshal(jsonDoc, &x); err != nil {
                return err
        }

        *i = Item(x)

        return nil
}

func main() {
        var i Item
        if err := json.Unmarshal(jsonDoc, &i); err != nil {
                log.Fatal(err)
        }

        fmt.Printf("%#v\n", i)
}

在操场上试试:https://play.golang.org/p/0qibavRJbwi