json数据传输格式在现在前后端开发很常用,微服务开发现在也很流行,使用golang开发微服务使用的是google的GRPC框架,数据传输采用protocolbuffer,通常前端数据使用json,而经过后端微服务传输使用proto,这时如果采用直接赋值方式,当数据量大了就要写很多赋值语句。那么能不项json和xml直接序列化和反序列化方式转换呢?答案是有的!
protocol buffer官方提供了一个包github.com/golang/protobuf/jsonpb
这个包里面有个json_test.go文件,可以参考如何转换
参考其中一个函数
func TestUnmarshalUnsetRequiredFields(t *testing.T) {
tests := []struct {
desc string
pb proto.Message
json string
}{
{
desc: "direct required field missing",
pb: &pb2.MsgWithRequired{},
json: `{}`,
},
{
desc: "direct required field set to null",
pb: &pb2.MsgWithRequired{},
json: `{"str": null}`,
},
{
desc: "indirect required field missing",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"subm": {}}`,
},
{
desc: "indirect required field set to null",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"subm": {"str": null}}`,
},
{
desc: "direct required bytes field missing",
pb: &pb2.MsgWithRequiredBytes{},
json: `{}`,
},
{
desc: "direct required bytes field set to null",
pb: &pb2.MsgWithRequiredBytes{},
json: `{"byts": null}`,
},
{
desc: "direct required wkt field missing",
pb: &pb2.MsgWithRequiredWKT{},
json: `{}`,
},
{
desc: "direct required wkt field set to null",
pb: &pb2.MsgWithRequiredWKT{},
json: `{"str": null}`,
},
{
desc: "any containing message with required field set to null",
pb: &pb2.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
},
{
desc: "any containing message with missing required field",
pb: &pb2.KnownTypes{},
json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
},
{
desc: "missing required in map value",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
},
{
desc: "required in map value set to null",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
},
{
desc: "missing required in slice item",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"slice_field": [{}, {"str": "hi"}]}`,
},
{
desc: "required in slice item set to null",
pb: &pb2.MsgWithIndirectRequired{},
json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
},
{
desc: "required inside oneof missing",
pb: &pb2.MsgWithOneof{},
json: `{"msgWithRequired": {}}`,
},
{
desc: "required inside oneof set to null",
pb: &pb2.MsgWithOneof{},
json: `{"msgWithRequired": {"str": null}}`,
},
{
desc: "required field in extension missing",
pb: &pb2.Real{},
json: `{"[jsonpb.extm]":{}}`,
},
{
desc: "required field in extension set to null",
pb: &pb2.Real{},
json: `{"[jsonpb.extm]":{"str": null}}`,
},
}
for _, tc := range tests {
if err := UnmarshalString(tc.json, tc.pb); err == nil {
t.Errorf("%s: expected error while unmarshaling with unset required fields %s", tc.desc, tc.json)
}
}
}
上面的代码比较多,我们可以来做个简单点的做个实验
1、首先新建一个工程,在工程目录下新建一个文件夹myproto用来存放proto文件,编写proto文件my.proto
syntax = "proto3";
option go_package ="./myproto";#加这一行主要是方便编译后的文件存放到这个目录下
message Message {
string say = 1;
}
2、然后编译proto文件生成my.pb.go,
命令:protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/addressbook.proto
官方文档:https://developers.google.cn/protocol-buffers/docs/gotutorial
其中一段是:
type Message struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Say string `protobuf:"bytes,1,opt,name=say,proto3" json:"say,omitempty"`
}
看到json:"say,omitempty"这个标签是不是很熟悉!
3、到main.go文件编写测试代码
import (
"Test/myproto"
"github.com/golang/protobuf/jsonpb"
"fmt"
)
func Test() {
jsonstr := `{"say":"Tom"}`
pb := &myproto.Message{}
if err := jsonpb.UnmarshalString(jsonstr, pb); err == nil {
fmt.Errorf("err:%s\n", err)
}
fmt.Printf("pb.say:%s\n", pb.Say)
}
func main(){
Test()
}
至此测试实验完毕!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)