Reputation: 3059
I have some JSON that I wish to unmarshal in Go. One of the top-level keys of the JSON dictionary has a value that is also parsable JSON. For example:
{
"Name": "Tony",
"Age": 50,
"Extra": {\"Weight\":180}
}
I have a corresponding struct that I want to unmarsal to:
type Person struct {
Name string
Age int
Extra []byte
}
I want the Extra
key to be a byte array because the JSON structure will vary and the structure of it is not important to the program being written. The program simply needs to push this data along down the line as a byte array.
How can I coax the Go JSON encoder to handle the value of extra
like this?
Upvotes: 0
Views: 183
Reputation: 120999
Use json.RawMessage
or interface{}
:
type Person struct {
Name string
Age int
Extra json.RawMessage
}
type Person struct {
Name string
Age int
Extra interface{}
}
With a json.RawMessage, the data is pushed down the line as a slice of bytes. With an interface{}
, the data is unmarshaled to Go values (bool, float64, string, []interface{}, map[string]interface{}, nil) and marshaled back to JSON. Both options pass arbitrary JSON through the application. If the application does not have a reason to use one or the other, then json.RawMessage
is probably the better choice because it's faster.
Upvotes: 0
Reputation: 6238
You have two options:
json.RawMessage
Here you have to slightly change your struct:
type Person struct {
Name string
Age int
Extra *json.RawMessage
}
then, you can Unmarshal
as usual
person := Person{}
err := json.Unmarshal(raw_bytes, &person)
// handle err
finally, you can Unmarshal Extra
again, you can even do some assertion type on it to previously detect the type
var extra_option_1 string
extra_option_2 := AnotherStruct{}
err := json.Unmarshal(raw_bytes, &extra_option_1)
// handle err
// or
err := json.Unmarshal(raw_bytes, &extra_option_2)
// handle err
map[string]interface{}{}
- honestly not so useful in your caseYou can directly unmarshal "unknown" or dynamics payloads using a general map[string]interface{}{}
.
BUT I discourage this usage because is slower and you should always know what to expect.
Anyway, hereafter is a pseudo code:
payload := map[string]interface{}{}
err := json.Unmarshal(raw_bytes, &payload)
// handle err
In this last case, you need even to do assertion to each field.
Upvotes: 1