英文:
How to parse protocol buffer message and create json out of it?
问题
这是我的最小.proto文件:
syntax = "proto3";
message getDhtParams {}
message DhtContents {
string dht_contents=1;
}
service MyApp {
rpc getDhtContent(getDhtParams) returns (DhtContents) {}
}
与上述.proto文件相关的两个要点:
- 这是一个最小化的文件,实际上还有更多内容。
- 服务器已经生成并正在运行,服务器是用Python实现的。
我正在用Go编写客户端。以下是我编写的获取代码:
func fetchDht() (*pb.DhtContents, error) {
// Set up a connection to the server.
address := "localhost:9998"
conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewMyAppClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := client.GetDhtContent(ctx, &pb.GetDhtParams{})
if err != nil {
return nil, errors.New("could not get dht contents")
}
return r, nil
}
为了简单起见,我简化了输出,但输出看起来类似于这样:
dht_contents:"{'node_ids': ['dgxydhlqoopevxv'], 'peer_addrs': [['192.168.1.154', '41457']], 'peer_meta': [{'peer_id': {'nodeID': 'dgxydhlqoopevxv', 'key': 'kdlvjdictuvgxspwkdizqryr', 'mid': 'isocvavbtzkxeigkkrubzkcx', 'public_key': 'uhapwxnfeqqmnojsaijghhic', '_address': 'xklqlebqngpkxb'}, 'ip_addrs': ['192.168.1.154', '41457'], 'services': [{'service_input': '', 'service_output': '', 'price': 0}], 'timestamp': 1661319968}]}"
关于此响应的几个要点:
- 它以
dht_contents:
开头,我知道这是DhtContents
消息的一个字段。 - 这可能是服务器端的问题;在这种情况下,我将通知服务开发人员。但是,封闭的JSON不是有效的JSON,因为它使用了单引号。
我的问题:
- 处理
dht_contents
的优雅方法是什么?一定有protobuf/grpc的方法。我希望获取双引号之间的内容。 - 如何将内容转换为JSON?我已经创建了用于解组的结构。
如果我能将类型为 *pb.DhtContents
的响应转换为 []byte
,那就足够了,从那里我可以将其转换为JSON。
英文:
Here is my minimal .proto file:
syntax = "proto3";
message getDhtParams {}
message DhtContents {
string dht_contents=1;
}
service MyApp {
rpc getDhtContent(getDhtParams) returns (DhtContents) {}
}
Two things to note related to the above proto file:
- It is a minimal file. There is a lot more to it.
- The server is already generated and running. The server is implemented in Python.
I am writing client in Go. And this is the fetching code I have come up with:
func fetchDht() (*pb.DhtContents, error) {
// Set up a connection to the server.
address := "localhost:9998"
conn, err := grpc.Dial(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewMyAppClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := client.GetDhtContent(ctx, &pb.GetDhtParams{})
if err != nil {
return nil, errors.New("could not get dht contents")
}
return r, nil
}
For sake of simplicity, I have tripped down the output, but the output looks something like this:
dht_contents:"{'node_ids': ['dgxydhlqoopevxv'], 'peer_addrs': [['192.168.1.154', '41457']], 'peer_meta': [{'peer_id': {'nodeID': 'dgxydhlqoopevxv', 'key': 'kdlvjdictuvgxspwkdizqryr', 'mid': 'isocvavbtzkxeigkkrubzkcx', 'public_key': 'uhapwxnfeqqmnojsaijghhic', '_address': 'xklqlebqngpkxb'}, 'ip_addrs': ['192.168.1.154', '41457'], 'services': [{'service_input': '', 'service_output': '', 'price': 0}], 'timestamp': 1661319968}]}"
A few things to note about this response:
- It starts with
dht_contents:
which I know is a field ofDhtContents
message. - This could be an issue from the server side; in that case I will inform the service developer. But the json enclosed is not a valid JSON as it uses single quotes.
My questions:
- What is an elegant way to deal with that
dht_contents
? There must be the protobuf/grpc way. I aim to get the contents between double quotes. - How do I convert the content to JSON? I have already created the struct to unmarshal.
It would be enough if I am also able to convert the response which is of type *pb.DhtContents
to []byte
, from there I can convert it to JSON.
答案1
得分: 0
生成的代码应该有一个方法,该方法将从开头删除dht_contents:"
,并从末尾删除"
。
在你的情况下,该方法应该被称为GetDhtContents()
。
你可以修改你的fetchDht
函数,像这样:
func fetchDht() (string, error) {
address := "localhost:9998"
// ...
if err != nil {
return nil, errors.New("could not get dht contents")
}
return r.GetDhtContents(), nil
}
从那里开始,你可以通过将单引号替换为双引号来使其成为有效的 JSON。或者这个处理可以在服务端处理。
英文:
- The generated code should have a method which will get rid of
dht_contents:"
from the start and"
from the end.
In your case, that method should be called GetDhtContents()
.
You can modify your fetchDht
function to something like this:
func fetchDht() (string, error) {
address := "localhost:9998"
// ...
if err != nil {
return nil, errors.New("could not get dht contents")
}
return r.GetDhtContents(), nil
}
- From there on, you can work on making it a valid JSON by replacing single quotes to double quotes. Or it may be handled on the service end.
答案2
得分: 0
- 通过proto文件生成的方法可以从结果("r")中获取内容,然后使用r.Get...,你可以获取到内容。
- 将字符串转换为你想要的类型。
建议: - 将proto类型更改为字节(bytes)。
- 然后使用json.Unmarshal([r.Get...],[dst])进行转换。
英文:
- there is the methods generated by proto file to get the content from the result(the "r"), then use r.Get..., you could get the content.
- convert string to the type you want.
suggest: - change proto type to bytes
- then json.Unmarshal([r.Get...],[dst])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论