使用 oneOf protobuf 字段将 yaml 解组为 proto3

unmarshal yaml to proto3 with oneOf protobuf field

我有一个结构如下的原型消息:

syntax = "proto3";

message Bar {
  int64 id = 1;
  string name = 2;
  int64 value = 3;
}

message Msg {
  int32 baz = 1;
  oneof some_union {
     string foo = 2;
     Bar bar = 3;
  }
}

我可以想到两种方法来编写与消息等效的 yaml。 在第一种方法中,请参见下面的示例,它分配 "some_union": null 并且没有在字段“foo”中设置任何值。

baz: 0
foo: "some_string"

在第二种方法中,请参见下面的示例,它会抛出一个错误 cannot unmarshal object into Go struct field

baz: 0
some_union:
  foo: "some_string"

我正在使用 github.com/ghodss/yaml 包将 yaml 解组为原始消息。

tl;博士;

您需要使用 protojson.UnmarshaloneOf 字段中正确获取值。


我创建了以下原型定义

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  oneof avatar {
    string imageUrl = 4;
    bytes imageData = 5;
  }
}

然后我能够创建一个 YAML 文件,它被正确读取。

---
name: Harry Potter
id: 1
email: harry@potter.com
imageUrl: https://picsum.photos/id/1005/200

唯一的问题是,如果我执行以下操作,

yamlBytes, _ := ioutil.ReadFile("testdata/person.yaml")
person := &pb.Person{}
yaml.Unmarshal(yamlBytes, person)

imageUrl的值没有设置,跟你说的一样

您需要这样做 - 首先将 YAML 转换为 JSON,然后使用 protojson.Unmarshal

yamlBytes, _ := ioutil.ReadFile("testdata/person.yaml")
person := &pb.Person{}
jsonBytes, _ := yaml.YAMLToJSON(yamlBytes)
protojson.Unmarshal(jsonBytes, person)

那么你就设置了 imageUrl 的正确值。

这是完整代码的 link - https://github.com/mbtamuli/GoLearnGo/tree/master/protobufs. You can see it in action in here - https://replit.com/@mbtamuli/didactic-train