【问题标题】:unmarshal yaml to proto3 with oneOf protobuf field使用 oneOf protobuf 字段将 yaml 解组为 proto3
【发布时间】:2021-07-05 07:24:36
【问题描述】:

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

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 解组为原始消息。

【问题讨论】:

  • 您的 baz 定义属于 string 类型,但您正在编组一个整数。
  • @colm.anseo 这只是一个问题,因为使用了github.com/ghodss/yaml。 YAML 本身完全满足于将 0 解析为字符串并直接使用 go-yaml 将允许这样做。但是,包装器首先将输入转换为 json,其中 0始终一个整数,这会导致错误。
  • 抱歉造成误会。我已经更新了这个问题。让baz 是一个整数。问题在于 foo 字段是 oneOf 类型并且不允许 yaml 进行结构转换。
  • 您尚未共享FooBar 消息定义。
  • 我已更新问题以提及 fooBar 的定义。但我认为这不会有太大帮助,问题是我无法为 oneOf 类型下的任何字段设置值。

标签: go yaml protocol-buffers


【解决方案1】:

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 的正确值。

这里是完整代码的链接 - https://github.com/mbtamuli/GoLearnGo/tree/master/protobufs。你可以在这里看到它的实际效果 - https://replit.com/@mbtamuli/didactic-train

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-01
    • 1970-01-01
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多