Try it yourself with our free Json Formatter tool — runs entirely in your browser, no signup needed.

How to Format JSON in Go

How to format JSON in Go

Formatting JSON data is an essential task in many applications, as it makes the data more human-readable and easier to debug. In Go, formatting JSON data can be achieved using the encoding/json package. This guide will walk you through the process of formatting JSON data in Go, covering the most common use cases, edge cases, and providing practical tips for performance optimization.

Quick Example

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Email string `json:"email"`
}

func main() {
	person := Person{
		Name:  "John Doe",
		Age:   30,
		Email: "john@example.com",
	}

	jsonData, err := json.MarshalIndent(person, "", "  ")
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(string(jsonData))
}

Step-by-Step Breakdown

Let's break down the code example above:

  • We import the encoding/json package, which provides functions for encoding and decoding JSON data.
  • We define a Person struct with three fields: Name, Age, and Email. We use struct tags to specify the JSON key names for each field.
  • In the main function, we create a Person instance and populate its fields.
  • We use the json.MarshalIndent function to encode the Person instance to a JSON byte slice. The MarshalIndent function takes three arguments: the value to be encoded, the prefix to be added to each line, and the indentation string.
  • We check for any errors that occurred during encoding and print the error message if necessary.
  • Finally, we print the formatted JSON data as a string.

Handling Edge Cases

Empty/Null Input

When handling empty or null input, we need to ensure that our code does not panic or produce unexpected results. Here's an example:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

func main() {
	var person *Person
	jsonStr, err := formatJSON(person)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(jsonStr)
}

In this example, we define a formatJSON function that takes an interface{} argument and returns a formatted JSON string. If the input is nil, the json.MarshalIndent function will return an error, which we handle by returning an empty string and the error.

Invalid Input

When handling invalid input, we need to ensure that our code does not panic or produce unexpected results. Here's an example:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

func main() {
	var person = []byte(" invalid json ")
	jsonStr, err := formatJSON(person)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(jsonStr)
}

In this example, we pass an invalid JSON byte slice to the formatJSON function. The json.MarshalIndent function will return an error, which we handle by returning an empty string and the error.

Large Input

When handling large input, we need to ensure that our code does not consume excessive memory or produce unexpected results. Here's an example:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

func main() {
	var person = make([]Person, 10000)
	for i := range person {
		person[i].Name = "John Doe"
		person[i].Age = 30
		person[i].Email = "john@example.com"
	}
	jsonStr, err := formatJSON(person)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(jsonStr)
}

In this example, we create a large slice of Person instances and pass it to the formatJSON function. The json.MarshalIndent function will consume memory proportional to the size of the input, but it will not produce unexpected results.

Unicode/Special Characters

When handling Unicode or special characters, we need to ensure that our code produces the correct output. Here's an example:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

func main() {
	var person = Person{
		Name:  "John ",
		Age:   30,
		Email: "john@example.com",
	}
	jsonStr, err := formatJSON(person)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(jsonStr)
}

In this example, we create a Person instance with a Unicode character in the Name field. The json.MarshalIndent function will produce the correct output, including the Unicode character.

Common Mistakes

Mistake 1: Not Handling Errors

func formatJSON(data interface{}) string {
	jsonData, _ := json.MarshalIndent(data, "", "  ")
	return string(jsonData)
}

Corrected code:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

Mistake 2: Not Using Struct Tags

type Person struct {
	Name  string
	Age   int
	Email string
}

Corrected code:

type Person struct {
	Name  string `json:"name"`
	Age   int    `json:"age"`
	Email string `json:"email"`
}

Mistake 3: Not Handling Large Input

func formatJSON(data interface{}) string {
	jsonData, _ := json.MarshalIndent(data, "", "  ")
	return string(jsonData)
}

Corrected code:

func formatJSON(data interface{}) (string, error) {
	jsonData, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(jsonData), nil
}

Performance Tips

Tip 1: Use json.MarshalIndent Instead of json.Marshal

The json.MarshalIndent function is more efficient than json.Marshal because it produces formatted output, which reduces the amount of memory allocated.

Tip 2: Avoid Using interface{}

Using interface{} can lead to performance issues because it requires type assertions and can lead to memory allocation.

Tip 3: Use json.NewEncoder for Streaming JSON

The json.NewEncoder function allows you to stream JSON data, which can improve performance for large inputs.

FAQ

Q: How do I format JSON data in Go?

A: You can use the json.MarshalIndent function to format JSON data in Go.

Q: How do I handle errors when formatting JSON data?

A: You should always check for errors when formatting JSON data and handle them accordingly.

Q: How do I handle large input when formatting JSON data?

A: You should use the json.MarshalIndent function, which is designed to handle large input.

Q: How do I handle Unicode or special characters when formatting JSON data?

A: You should use the json.MarshalIndent function, which produces the correct output for Unicode or special characters.

Q: What is the difference between json.Marshal and json.MarshalIndent?

A: The json.MarshalIndent function produces formatted output, while json.Marshal produces compact output.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp