Highly recommend to read article JSON and Go if you are new to this area or want to bring the memory back.
In Golang, we usually use struct with struct tag to unmarshl/marshal JSON object data, for example, if the JSON object is:
1 | { |
The corresponding go struct:
1 | type Response struct { |
What is struct tag in golang please see: https://stackoverflow.com/questions/10858787/what-are-the-uses-for-struct-tags-in-go
Please note that only exported field
(upper case) in struct will be
encoded/decoded, and struct tag can help rename, if there is no struct tag, the
exact struct field name will be used as JSON key name in marshalling.
For unmarshal if there is no corresponding JSON field, the struct field will be
assigned the default zero
value of that type, for example:
1 | // using raw string quote `` to avoid any escape chars |
Because the user_info
JSON data is missing, so UserInfo
gets a struct value
with default value on all fields UserInfo:{Age:0 Height:0}
, but this cannot
tell if the user_info
is really missing or it has value but all 0.
To solve this, we can use pointer for nested struct field:
1 | type Response struct { |
And run again, the output will be:
1 | {Page:1 UserInfo:<nil>} |
By checking it is nil
, we can tell the JSON data is missing.
For Arbitrary JSON Object Data
If there are unknown fields in JSON data, we can use interface and type assertion to help decode the JSON data, for example:
From blog JSON and Go, the json
module uses
interface{}
to store arbitrary JSON objects or arrays and access them by
type asseration with underlying map[string]interface{}
.
I have encountered the case that a struct field the marshal and unmarshal have
to use different type due to some reasons, so I have to use interface{}
for
that struct field and use assertion to access it.
Omit The Field If Not Exist
The “omitempty” option specifies that the field should be omitted from the marshal(encoding) if the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string.
1 | type Example struct { |
Exclude The Field
This field will be skipped in either Marshal or Unmarshal.
1 | type Example struct { |
Non-Object JSON Data
The JSON is not always in object format, it can be a array, single string or number, so to unmarshal them we need to use right golang data type:
- JSON array -> golang slice
- JSON string -> golang string
- JSON number -> golang number
For example:
1 | blob := `"hello, json"` |
Customizing Marshal/Unmarshal
This UnmarshalJSON
method can be used to customize the unmarshal process, it
is from Unmarshaler interface.
In this example, we want to unmarshal a JSON string to a golang struct, the JSON string is like:
1 | "{\"name\": \"peter\", \"code\": 20001, \"message\": \"peter is sick off today!\"}" |
1 | type ExampleError struct { |
There is another example about customized marshal and unmarshal, redact on top of golang json module example:
1 | package main |
Unmarshal String to Number
This is tricky and useful in some cases, we want to unmarshal a string encoded
number to golang uint64
, so in the struct you can use tag string
, for
example:
1 | type Example struct { |
From document:
The string
option signals that a field is stored as JSON inside a JSON-encoded
string. It applies only to fields of string, floating point, integer, or boolean
types.
JSON Encoder/Decoder
When to use marshal/unmarshal and encoder/decoder, reference question:
-
Use
json.Decoder
if your data is coming from an io.Reader stream, or you need to decode multiple values from a stream of data, for example the HTTP response, this can be memory efficiency because it does not load all data into memory. -
Use
json.Unmarshal
if you already have the JSON data in memory.
Also from JSON and Go: Due to the ubiquity of Readers and Writers, these Encoder and Decoder types can be used in a broad range of scenarios, such as reading and writing to HTTP connections, WebSockets, or files.