protobuf中坑人的2点

  • Post author:
  • Post category:其他


protobuf中坑人的2点:

1.oneof类型不能通过json反序列化

2.最里层的message没有null值,都会被赋该类型的默认值

1.oneof类型不能通过json反序列化

定义一个这样的protobuf消息:

message EnvValue {
	oneof val {
		string s = 1;
		double f = 2;
	}
}

生成的go语言代码对应的结构为:

type EnvValue struct {
	// Types that are valid to be assigned to Val:
	//	*EnvValue_S
	//	*EnvValue_F
	Val                  isEnvValue_Val `protobuf_oneof:"val"`
	XXX_NoUnkeyedLiteral struct{}                  `json:"-" bson:"-"`
	XXX_unrecognized     []byte                    `json:"-" bson:"-"`
	XXX_sizecache        int32                     `json:"-" bson:"-"`
}

定义一个EnvValue对象envValue:

envValue := &pb.EnvValue{
	Val: &pb.EnvValue_F{
		F: 5,
	},
}

使用json.Marshal方法将序列化为json:

{
  "val": {
      "Val": {
          "F": 4
      }
  }
}

但是当用json.Unmarshal方法将该json反序列化为EnvValue对象,得到的却是如下:

envValue := &pb.EnvValue{
	Val: nil,
}

可以看到,protobuf的oneof类型不能通过json反序列化

所以,有通过json反序列化为protobuf的需求时,尽量不要使用oneof类型。

2.最里层的message没有null值,都会被赋该类型的默认值

定义一个protobuf的消息:

message Request {
	map<string, Value> env = 1;
}

message Value {
	double f = 1;
}

生成的go语言代码对应的结构为:

type Request struct {
	Env                  map[string]*Value `protobuf:"bytes,1,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
	XXX_NoUnkeyedLiteral struct{}                        `json:"-" bson:"-"`
	XXX_unrecognized     []byte                          `json:"-" bson:"-"`
	XXX_sizecache        int32                           `json:"-" bson:"-"`
}

构造出对应的json:

{
  "env": {
    "level": null
  },
}

用json.Unmarshal方法将该json反序列化为Request对象,得到如下:

request = &pb.Request{
	Env: map[string]*pb.Value{
		"level": {
			Val: &pb.Value{
				F: 0,
			},
		},
	},
}

可以看到,即使赋

最里层

的message为null,protobuf也会给它默认值填充。但是如果赋


“env”: null


,反序列出来的protobuf也为null。

所以,有通过json反序列化为protobuf的需求时,尽量不要赋最里层的message为null



版权声明:本文为a13545564067原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。