When writing custom JSON marshalers in Go, calling json.Marshal on the same type inside MarshalJSON creates an infinite loop. The solution is to define a local type with the same underlying type inside the function, then cast the value to that local type before marshaling. Since the local type doesn't inherit the custom MarshalJSON method, the loop is broken. This technique works for wrapping values in arrays, deeply nesting objects, or any scenario where you need slightly different JSON output than the standard library provides. Using json.RawMessage and json.Marshal for the final output is also recommended over manual string concatenation for robustness.
Table of contents
ExamplesWhy the standard library failsWriting a custom marshalerA better solutionBreaking the loop with a local typeAnother improvementAnother exampleBreaking the loopConclusionI’d love your feedback8 Impressions