MrE MrE - 4 months ago 51
JSON Question

Golang: Unmarshal/Marshal json with int set to 0 does not seem to work

I am trying to parse a json object into a struct, but integer values set to 0 won't work.

q := []byte(`{"string":"this is a string", "integer": 0}`)

type Test struct {
String string `json:"string,omitempty"`
Integer int `json:"integer,omitempty"`
}

var qq Test
if err := json.Unmarshal(q, &qq); err != nil {
panic(err)
}

queryStr, err := json.Marshal(qq)
if err != nil {
panic(err)
}
fmt.Println(string(queryStr))
// Output: {"string": "this is a string"}


if I set the integer to anything but 0, this works fine.

even if I Unmarshal the object and set the Integer field to 0, Marshalling it back removes the "integer" field.

Why? and how to get around this?

EDIT:

from what I gather from the comments,
omitempty
triggers when value is 0. So now the disappearance makes sense.

I'm parsing json, editing it and forwarding it to another service, so this is unfortunate, especially as field not present defaults to other values than 0, and I would prefer not having to feed in the defaults for the downstream API.

So is there a way to omit empty values but keep 0?

or change empty to something else?

Do I need to have 2 structs: one for input and one for output?

Answer

Use a pointer for the fields, so that the zero value of the JSON type can be differentiated from the missing value.

type Test struct {
    String  *string `json:"string,omitempty"`
    Integer *int    `json:"integer,omitempty"`
}

https://play.golang.org/p/yvYSHxubLy