How to unmarshall JSON into protobuff with different-case fields?

huangapple go评论84阅读模式
英文:

How to unmarshall JSON into protobuff with different-case fields?

问题

从Python转过来。我需要将一个JSON解组成一个Protobuff消息。类似这样:

{"jobId": "abc"}

我已经按照相同的方式定义了我的proto文件字段,希望在消息构建过程中能够轻松匹配:

string jobId = 1;

Protobuff将字段名更改为驼峰命名法。因此,当我尝试解组时,会收到以下错误:

  10     msg := &Message{}
  11     err := protojson.Unmarshal([]byte(MessageData), msg)

>> msg.jobId undefined (type *Message has no field or method jobId, but does have JobId)

有没有一种简洁的方法来实现这个?即不依赖外部库,如果不行,也不希望使用自定义的处理方法。

请注意,我已经在使用protojson

英文:

Coming from Python. I need to unmarshal a JSON into a protobuff message. Something like:

{"jobId": "abc"}

I defined my proto files field exactly the same, hoping for an easy match up during message contruction:

string jobId = 1;

Protobuff changes the fields names into CamelCase. Thus when I am trying to unmarshal I receive the error:

  10     msg := &Message{}
  11     err := protojson.Unmarshal([]byte(MessageData), msg)

>> msg.jobId undefined (type *Message has no field or method jobId, but does have JobId)

What is a clean way to achieve this? i.e. preferring no external dependencies, and if not, preferring no bespoke wrangling.

Please note that I am already using protojson.

EDIT:

In Python, google.protobuf.json_format.Parse does this: https://github.com/protocolbuffers/protobuf/blob/master/python/google/protobuf/json_format.py#L403

答案1

得分: 1

我已经尝试过这个,并且运行得很好。我将解释我是如何做到的。

我的 message.proto 文件如下所示。它包含在 proto-test 目录中,结构如下:

myProject
 |
 +-- main.go
 |    
 +-- proto-test
 |  |  
 |  +-- message.proto
syntax = "proto3";
option go_package = "/proto_msg";

package proto_msg;

message Message {
    string jobId = 1;
    bool sentOnce = 2;
}

在 proto-test 目录中运行 proto 命令,以生成与 message.proto 相关的 go 文件 message.pb.go,它将被创建在 proto_msg 目录下,使用 proto_msg go package。

命令: protoc -I=. --go_out=. ./message.proto

myProject
 |
 +-- main.go
 |    
 +-- proto-test
 |  |  
 |  +-- message.proto
 |  +-- proto_msg
 |     |
 |     +--message.pb.go

然后创建以下 Go message 结构体。

type Message struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	JobId    string `protobuf:"bytes,1,opt,name=jobId,proto3" json:"jobId,omitempty"`
	SentOnce bool   `protobuf:"varint,2,opt,name=sentOnce,proto3" json:"sentOnce,omitempty"`
}

然后运行以下主要代码。

package main

import (
	msg "myProject/proto-test/proto_msg"
	"fmt"
	"google.golang.org/protobuf/encoding/protojson"
	"log"
)

func main() {
	m := &msg.Message{}
	MessageData := `{"jobId": "abc", "sentOnce": true}`

	err := protojson.Unmarshal([]byte(MessageData), m)
	if err != nil {
		log.Panic(err)
	}

	fmt.Println(m.String())
}

它成功运行,并输出为

jobId:"abc" sentOnce:true
英文:

I have tried this and worked fine. I will explain how I have done this.

my message.proto file as below. This is contained in proto-test directory as

myProject
 |
 +-- main.go
 |    
 +-- proto-test
 |  |  
 |  +-- message.proto
syntax = "proto3";
option go_package = "/proto_msg";

package proto_msg;

message Message {
    string jobId = 1;
    bool sentOnce = 2;
}

After I have run the proto command inside the proto-test directory to make the go file relevant to the message.proto message.pb.go file is created inside the proto_msg directory with the proto_msg go package.

Command: protoc -I=. --go_out=. ./message.proto

myProject
 |
 +-- main.go
 |    
 +-- proto-test
 |  |  
 |  +-- message.proto
 |  +-- proto_msg
 |     |
 |     +--message.pb.go

Ans created Go message struct as below.

type Message struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	JobId    string `protobuf:"bytes,1,opt,name=jobId,proto3" json:"jobId,omitempty"`
	SentOnce bool   `protobuf:"varint,2,opt,name=sentOnce,proto3" json:"sentOnce,omitempty"`
}

then after I have run the following main code.

package main

import (
	msg "myProject/proto-test/proto_msg"
	"fmt"
	"google.golang.org/protobuf/encoding/protojson"
	"log"
)

func main() {
	m := &msg.Message{}
	MessageData := `{"jobId": "abc", "sentOnce": true}`

	err := protojson.Unmarshal([]byte(MessageData), m)
	if err != nil {
		log.Panic(err)
	}

	fmt.Println(m.String())
}

It ran successfully and output is

jobId:"abc" sentOnce:true

huangapple
  • 本文由 发表于 2021年10月20日 06:39:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/69638367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定