Home > Enterprise >  How to allow "omitempty" only Unmarshal() and not when Marshal()?
How to allow "omitempty" only Unmarshal() and not when Marshal()?

Time:11-19

I have a struct:

type MyStruct struct {
  a string `json:"a,omitempty"`
  b int `json:"b"`
  c float64 `json:"c,omitempty"`
}

How would I make the fields a and c optional when doing json.Unmarshal(...), but always present in the output json -- when doing json.Marshal(...)?

CodePudding user response:

You don't need to worry about omitempty when unmarshalling a JSON string. The struct member will get set to its zero value if the attribute is missing from the JSON input.

You do however need to export your struct's members (use A, not a).

go playground: https://play.golang.org/p/vRs9NOEBZO4

type MyStruct struct {
    A string  `json:"a"`
    B int     `json:"b"`
    C float64 `json:"c"`
}

func main() {
    jsonStr1 := `{"a":"a string","b":4,"c":5.33}`
    jsonStr2 := `{"b":6}`

    var struct1, struct2 MyStruct

    json.Unmarshal([]byte(jsonStr1), &struct1)
    json.Unmarshal([]byte(jsonStr2), &struct2)

    marshalledStr1, _ := json.Marshal(struct1)
    marshalledStr2, _ := json.Marshal(struct2)

    fmt.Printf("Marshalled struct 1: %s\n", marshalledStr1)
    fmt.Printf("Marshalled struct 2: %s\n", marshalledStr2)
}

You can see in the output that for struct2, members A and C get their zero values (empty string, 0). omitempty isn't present in the struct definition, so you get all the members in the json string:

Marshalled struct 1: {"a":"a string","b":4,"c":5.33}
Marshalled struct 2: {"a":"","b":6,"c":0}

If you are looking to distinguish between A being an empty string and A being null/undefined, then you'll want your member variable to be a *string, not a string:

type MyStruct struct {
    A *string `json:"a"`
    B int     `json:"b"`
    C float64 `json:"c"`
}

func main() {
    jsonStr1 := `{"a":"a string","b":4,"c":5.33}`
    jsonStr2 := `{"b":6}`

    var struct1, struct2 MyStruct

    json.Unmarshal([]byte(jsonStr1), &struct1)
    json.Unmarshal([]byte(jsonStr2), &struct2)

    marshalledStr1, _ := json.Marshal(struct1)
    marshalledStr2, _ := json.Marshal(struct2)

    fmt.Printf("Marshalled struct 1: %s\n", marshalledStr1)
    fmt.Printf("Marshalled struct 2: %s\n", marshalledStr2)
}

Output is now closer to the input:

Marshalled struct 1: {"a":"a string","b":4,"c":5.33}
Marshalled struct 2: {"a":null,"b":6,"c":0}
  • Related