解析不一致的JSON

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

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

那么你能控制的程度有多大?我可以为你提供一些场景,并希望其中一些能符合你的目的 解析不一致的JSON

首先记住一般规则:

在 Golang 中,如果一个 JSON 键找不到匹配的结构字段,它将不会被解组。

这意味着对于 JSON 结构中的键名,在解组时,它会在 Golang 结构中的相同级别上不区分大小写地查找具有相同名称的字段。如果查找失败,该键将不会被解组。

例如,一个名为 foo1 的键将在 Golang 结构的相同缩进级别上查找名为 foo1 的字段。但它也与 Foo1FoO1 匹配,因为这种匹配是不区分大小写的。

请记住,你还可以使用字段标签来指定字段名称。请参阅官方页面

一些 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 解析不一致的JSON

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.

huangapple
  • 本文由 发表于 2016年3月31日 08:28:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/36322141.html
匿名

发表评论

匿名网友

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

确定