英文:
Unmarshal inconsistent JSON
问题
我有一个无法控制的 JSON 数据,像这样:
{
"foo1":{
"a":{
"up":10,
"down":5
}
},
"foo2":{
"a":{
"up":1,
"down":1
}
},
"bar":{
"up":11,
"down":6
}
}
"foo1" 和 "foo2" 是动态的。
我该如何在 Go 中正确地解组这个结构?
如果我可以告诉 Go 不要尝试反序列化 "bar"(不一致的属性),那就可以了。
英文:
I have JSON (that I cannot control) like this:
{
"foo1":{
"a":{
"up":10,
"down":5
}
},
"foo2":{
"a":{
"up":1,
"down":1
}
},
"bar":{
"up":11,
"down":6
}
}
"foo1" and "foo2" are dynamic.
How can I properly unmarshal this structure in go?
It would be okay if I could just tell go to not try to deserialize "bar" (the inconsistent property).
答案1
得分: 3
Go默认情况下会忽略在解组成结构体时未指定的字段。
在这种情况下,你的结构体应该设置如下:
type NestedProp2 struct {
Up int
Down int
}
type NestedProp struct {
A NestedProp2
}
type Prop struct {
Foo1 NestedProp
Foo2 NestedProp
}
当你调用json.Unmarshal
函数时,额外的属性将不会被反序列化:
var prop Prop
err := json.Unmarshal(jsonBlob, &prop)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", prop)
因此,你将得到以下输出:
{Foo1:{A:{Up:10 Down:5}} Foo2:{A:{Up:1 Down:1}}}
你可以在这里看到它的实际运行效果。
英文:
Go will by default ignore fields unspecified in the struct you unmarshal into.
In this case, your structure would be set up like this:
type NestedProp2 struct {
Up int
Down int
}
type NestedProp struct {
A NestedProp2
}
type Prop struct {
Foo1 NestedProp
Foo2 NestedProp
}
When you call the the json.Unmarshal function, the extra property will not be deserialized:
var prop Prop
err := json.Unmarshal(jsonBlob, &prop)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", prop)
So you get the following output:
{Foo1:{A:{Up:10 Down:5}} Foo2:{A:{Up:1 Down:1}}}
You can see it in action here.
答案2
得分: 0
你说:
> 我有一个我无法控制的 JSON
那么你能控制的程度有多大?我可以为你提供一些场景,并希望其中一些能符合你的目的
首先记住一般规则:
在 Golang 中,如果一个 JSON 键找不到匹配的结构字段,它将不会被解组。
这意味着对于 JSON 结构中的键名,在解组时,它会在 Golang 结构中的相同级别上不区分大小写地查找具有相同名称的字段。如果查找失败,该键将不会被解组。
例如,一个名为 foo1
的键将在 Golang 结构的相同缩进级别上查找名为 foo1
的字段。但它也与 Foo1
或 FoO1
匹配,因为这种匹配是不区分大小写的。
请记住,你还可以使用字段标签来指定字段名称。请参阅官方页面。
一些 JSON 字段的值不一致,可以被忽略。
这是 @gnalck 在他的答案中解决的情况。根据一般规则,如果这些不一致的字段找不到匹配,它们将不会被解组。因此,只需不将这些不一致的字段放入结构中,就可以解决问题。
一些 JSON 字段的值不一致,但不能被忽略。
在这种情况下,@gnalck 失败了,因为这些字段不能被忽略。现在一个更好的方法是将 bar
解组为 json.RawMessage
,这样你可以稍后解组。
JSON 对象的键是不确定的,它们的值也是不确定的。
在这种情况下,我们可以将整个 JSON 对象解组为 map[string]json.RawMessage
,然后稍后解组每个字段。当解组为 map 时,你可以遍历该 map 来获取所有字段,并稍后将它们解组为适当的结构。
英文:
You said:
> I have JSON (that I cannot control)
So to what extent you could control? Here I could provide you with some scenario, and hope some of them match your purpose
Remember the general rule first:
In Golang, if a JSON key failed to find a matched field in struct, it will not be unmarshalled.
This means, for a key name in a JSON struct, when unmarshalling, it will look for a field in a golang struct at the same level with the same name case-insensitively. If this search failed, this key won't be unmarshalled.
For example, a key named foo1
will look for a field name foo1
in a golang struct at the same indent level. However it also matches with Foo1
or FoO1
, since this matching is case-insensitive.
Remember, you could use field tag to specify the field name as well. Please take a look at the official page.
The value of some of the JSON fields are not consistent, and they could be ignored.
This is the case @gnalck solved in his answer. According to the general rule, if those inconsistent field failed to find a match, they will not be unmarshalled. Therefore, just don't put those inconsistent fields in the struct and you will be fine.
The value of some of the JSON fields are not consistent, but they could not be ignored.
In this case, @gnalck failed since those fields could not be ignored. Now a better way is to unmarshal bar
into a json.RawMessage
, so that you could unmarshal later.
The keys of the JSON object is undetermined, and their value is undetermined as well.
In this case, we could unmarshal the whole JSON object into a map[string]json.RawMessage
, and unmarshal each fields later. When unmarshalling to a map, you could iterate through the map to get all the fields, and unmarshal them into a proper struct later.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论