JSON to Go: Differences, Edge Cases & Pitfalls

Generate Go structs from JSON with json tags, omitempty choices and notes on where float64 damages large integers.

Go structs need exported fields to be serialised by encoding/json, which is why property names and json tags come in pairs. Numbers landing as float64 is inherent to Go decoding; anything that must be an integer needs a manual change to int64.

Format Differences

AspectJSONGo struct
Field visibilityNot applicableLowercase fields are not serialised; must be exported
Key mappingAny key nameExplicit json:"snake_case" tags
NumbersOne number typeChoose float64 / int / int64 by hand
nullnull valuePointers, sql.NullString, or omitempty
Missing fieldsKey absentZero value (0, "", nil mean different things)
NestingNested objectsNested structs or map[string]interface{}
ArraysNativeSlices []T, homogeneous element type
Runtime costCheapReflection decoding is slower; codegen speeds it up

Edge Cases

  • With omitempty you cannot distinguish zero from unset, so use pointers when "present and zero" matters.
  • An empty array decodes to a nil slice and marshals back as null instead of [], which can change the contract.
  • Keys with hyphens or dots are not identifiers, so json:"..." tags are the only mapping.
  • Very long integers (order IDs) lose precision as float64; use string or int64.

Common Pitfalls

  • Manually lowercasing fields to "look idiomatic" makes serialisation emit an empty object with no error.
  • Money as float64 accumulates cent-level error, discovered during reconciliation.
  • An empty array round-trips to null and the front end throws while iterating.
  • Sprinkling omitempty strips explicitly-set zero values and loses business meaning.

Related Tools