解组不一致的JSON

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).

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.

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.