Pretty-printing JSON means formatting your JSON output with proper indentation and line breaks.
Golang has a built-in “encoding/json” package that provides json.MarshalIndent() function that you can use to pretty-print JSON data with proper indentation and line breaks.

The basic working of json.MarshaIndent() function accepts data and converts it into JSON-formatted byte slice. It accepts a prefix for each line and indentation as the other two arguments.
package main import ( "encoding/json" "fmt" ) func main() { product := map[string]interface{}{ "item": "TV", "price": 3000, "features": []string{"DolbyAtmos", "DolbyVision"}, } // Marshal with indentation (2-space indent) jsonBytes, err := json.MarshalIndent(product, "", " ") if err != nil { panic(err) } fmt.Println(string(jsonBytes)) } // Output // { //. "features": [ // "DolbyAtmos", // "DolbyVision" // ], // "item": "TV", // "price": 3000 // }
In the above code, you can see that we passed product data, prefix as an empty string, and 2-space as indentation to format it correctly, and the commented printed output is pretty.
Always check errors after marshaling/unmarshaling. Use spaces instead of tabs for cross-platform consistency.
Custom Prefixes and Indentation Styles
As I discussed earlier, you can modify the prefix and indentation for specialized use cases (e.g., logging):
package main import ( "encoding/json" "fmt" ) func main() { product := map[string]interface{}{ "item": "TV", "price": 3000, "features": []string{"DolbyAtmos", "DolbyVision"}, } // Marshal with indentation (2-space indent) jsonBytes, _ := json.MarshalIndent(product, "LOG: ", "│ ") fmt.Println(string(jsonBytes)) }Output

Formatting existing JSON strings
What if you have already minified json string? How would you pretty print that? Well. in that case, you have to unmarshal that minified string first into an interface{} first and then re-marshal with indentation.
package main import ( "encoding/json" "fmt" ) func main() { minifiedJSON := `{"name":"Krunal","age":32,"shows":["Breaking Bad", "GoT"]}` var intermediate_obj interface{} if err := json.Unmarshal([]byte(minifiedJSON), &intermediate_obj); err != nil { panic(err) } formatted, err := json.MarshalIndent(intermediate_obj, "", "\t") if err != nil { panic(err) } fmt.Println(string(formatted)) } // Output // { // "age": 32, // "name": "Krunal", // "shows": [ // "Breaking Bad", // "GoT" // ] // }
Streaming JSON with json.Encoder
If you are dealing with large datasets or direct writing to io.Writer (e.g., HTTP responses, files), you can use json.Encoder() function.
package main import ( "encoding/json" "os" ) func main() { data := map[string]interface{}{"key": "value"} encoder := json.NewEncoder(os.Stdout) encoder.SetIndent("", " ") // 2-space indent if err := encoder.Encode(data); err != nil { panic(err) } } // Output // { // "key": "value" // }In this code, we created a JSON encoder that writes directly to os.Stdout (the terminal).
To set the Indentation for Pretty Printing, we used an encoder.SetIndent(“”, ” “) method for 2-space indent.
Conclusion
If your input JSON data is not large, you should use the “json.MarshalIndent()” function to pretty-print it.
For large JSON payloads:
- Use json.Decoder() and json.Encoder() to stream data.
- Avoid json.MarshalIndent() if memory usage is a concern.