英文:
Accept dynamic keys in proto struct when unmarshalling JSON
问题
我的Proto文件大致如下:
message Test {
Service services = 1;
}
message Service {
map<string, ServiceData> services = 1;
}
message ServiceData {
string command = 1;
string root = 2;
}
这个.proto文件可以支持以下这样的JSON结构:
{
"services": {
"service1": {
"command": "command1",
"root": "/"
},
"service2": {
"command": "command2",
"root": "/"
}
}
}
现在,我想要读取test.json文件并进行解组:
var test Test
err := json.Unmarshal([]byte(file), &test)
为了成功解组这个JSON,你需要对.proto文件进行以下更改:
message Test {
map<string, ServiceData> services = 1;
}
message ServiceData {
string command = 1;
string root = 2;
}
这样,你就可以成功解组这个JSON了。
英文:
My Proto file looks something like this:
message Test {
Service services = 1;
}
message Service {
string command = 1;
string root = 2;
}
This .proto can support a json like this:
{
"services": {
"command": "command2",
"root": "/"
},
}
But, I want to manage a json that looks like this:
{
"services": {
"service1": {
"command": "command1",
"root": "/"
},
"service2": {
"command": "command2",
"root": "/"
},
},
}
So, here all the services will have common structure but the key name will vary (i.e. "service1"
, "service2"
)
Now, I want to read the data from test.json and unmarshal it:
var test *Test
err := json.Unmarshal([]byte(file), &test)
What changes should I do in the .proto
so that I can unmarshall this json successfully?
答案1
得分: 2
使用 proto map:
message Test {
map<string, Service> services = 1;
}
message Service {
string command = 1;
string root = 2;
}
proto map 在 Go 中被编译为 map[K]V
,所以在这种情况下是 map[string]*Service
,这是建议的用于建模具有任意键的 JSON 的方式。
这将产生以下输出:
services:{key:"service1" value:{command:"command1" root:"/"}} services:{key:"service2" value:{command:"command2" root:"/"}}
示例程序:
package main
import (
"encoding/json"
"example.com/pb"
"fmt"
)
const file = `{
"services": {
"service1": {
"command": "command1",
"root": "/"
},
"service2": {
"command": "command2",
"root": "/"
}
}
}
`
func main() {
test := &pb.Test{}
err := json.Unmarshal([]byte(file), test)
if err != nil {
panic(err)
}
fmt.Println(test)
}
英文:
Use a proto map:
message Test {
map<string, Service> services = 1;
}
message Service {
string command = 1;
string root = 2;
}
The proto map is compiled to map[K]V
in Go, so map[string]*Service
in this case, which is the recommended way to model JSON with arbitrary keys.
This will give the following output:
services:{key:"service1" value:{command:"command1" root:"/"}} services:{key:"service2" value:{command:"command2" root:"/"}}
Example program:
package main
import (
"encoding/json"
"example.com/pb"
"fmt"
)
const file = `{
"services": {
"service1": {
"command": "command1",
"root": "/"
},
"service2": {
"command": "command2",
"root": "/"
}
}
}
`
func main() {
test := &pb.Test{}
err := json.Unmarshal([]byte(file), test)
if err != nil {
panic(err)
}
fmt.Println(test)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论