英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论