golang

Pretty JSON Printing in Go (Pretty Print JSON)

JavaScript or JSON, as we all know, is a popular and powerful data interchange format that is easy to read and write for both machines and humans. JSON is incredibly popular for a wide variety of applications, including but not limited to APIs and more.

It is therefore no surprise that Go has a native support to work with JSON data such as serializing and deserializing the JSON data. Whether you are parsing an API response or configuration files, storing the structure data, and more, Go has all the tools for that.

However, while JSON is epic for machines to parse, when it comes to us, it can be difficult to quickly format the output and understand the actual layout.

This is where pretty print comes into play. In this tutorial, we will explore the workings of JSON using Go and explore the methods that we can use to pretty print the JSON from the output.

JSON in Go

Before we get into pretty printing in JSON, let us start with the basics of working with JSON in Go.

Encoding JSON

JSON encoding refers to the process of converting the data from the native data structure into the JSON format.

In Go, we can perform the data encoding to JSON using the encoding/JSON. An example demonstration is as follows:

package main
import (
    "encoding/json"
    "fmt"
)

type Connection struct {
    Hostname string `json:"hostname"`
    Port     int    `json:"port"`
    Auth     string `json:"auth"`
}
func main() {
    conn := Connection{
        Hostname: "localhost",
        Port:     4493,
        Auth:     "root:password?auth=88su",
    }
    jsonBytes, err := json.Marshal(conn)
    if err != nil {
        fmt.Println("Error encoding JSON:", err)
        return
    }
    fmt.Println(string(jsonBytes))
}

In this example, we define a “Connection” struct and use the “json.Marshal” from the encode/JSON package to convert it into a JSON data.

The resulting JSON object is as follows:

{"hostname":"localhost","port":4493,"auth":"root:password?auth=88su"}

Decoding JSON

Decoding refers to the process of taking a JSON object and deconstructing it into a valid Go data structure.

As you can guess, we use the “json.Unmarshall” function as demonstrated in the following example code:

package main
import (
    "encoding/json"
    "fmt"
)

type Connection struct {
    Hostname string `json:"hostname"`
    Port     int    `json:"port"`
    Auth     string `json:"auth"`
}
func main() {
    jsonStr := `{"hostname":"localhost","port":4493,"auth":"root:password?auth=88su"}`
    var conn Connection
    err := json.Unmarshal([]byte(jsonStr), &conn)
    if err != nil {
        fmt.Println("Error decoding JSON:", err)
        return
    }
    fmt.Println("Hostname:", conn.Hostname)
    fmt.Println("Port:", conn.Port)
    fmt.Println("Auth:", conn.Auth)
}

In this example, we use the “json.Unmarshal” function to deconstruct (decode) the provided JSON string into a “Connection” struct.

The resulting values are as follows:

Hostname: localhost
Port: 4493
Auth: root:password?auth=88su

JSON Pretty Print in Go

With the basics of working with JSON out of the way, let us learn how to perform the pretty print in Go.

What Is Pretty Print?

JSON pretty print refers to the method of formatting the JSON data into a user-friendly format that is very easy to read for humans. This involves adding the features such as line breaks, adding spaces, and more.

This makes it easier for humans to visually parse and understand the structure of the JSON data.

The goal is to make the JSON output more organized and aesthetically pleasing.

The following is an example of a JSON string in its raw output form:

{"hostname":"localhost","port":4493,"auth":"root:password?auth=88su"}

This is the same JSON string with the pretty print feature turned on:

{
"hostname": "localhost",
"port": 4493,
"auth": "root:password?auth=88su"
}

You will notice that the second example is easier on the eyes and is very easy to read and understand.

Method 1: Using Json.MarshalIndent

The encoding/JSON package provides us with the “json.MarshalIndent” function which allows us to encode a Go data structure into JSON and preserve the indentation for pretty printing.

The syntax of the function is as follows:

func MarshalIndent(v any, prefix, indent string) ([]byte, error)

It behaves similar to the Marshal function but applies the indent format to the output.

An example is as follows:

func main() {
    conn := Connection{
        Hostname: "localhost",
        Port:     4493,
        Auth:     "root:password?auth=88su",
    }
    jsonBytes, err := json.MarshalIndent(conn, "", "    ")
    if err != nil {
        fmt.Println("Error encoding JSON:", err)
        return
    }
    fmt.Println(string(jsonBytes))
}

In our example, we tell the “MarshalIndent” function to preserve the indentation and use four spaces.

The resulting output is as follows:

{
"hostname": "localhost",
"port": 4493,
"auth": "root:password?auth=88su"
}

Method 2: Using the Custom Formatting

The second method to perform the JSON pretty print is defining our own custom struct and implement the “json.Marshaler” interface. This allows us to define a custom formatting for the JSON data as shown in the following example:

package main
import (
    "encoding/json"
    "fmt"
)
type Connection struct {
    Hostname string `json:"hostname"`
    Port     int    `json:"port"`
    Auth     string `json:"auth"`
}
func (c Connection) MarshalJSON() ([]byte, error) {
    formatted := fmt.Sprintf("{\n    "hostname": "%s",\n    "port": %d,\n    "auth": "%s"\n}", c.Hostname, c.Port, c.Auth)
    return []byte(formatted), nil
}
func main() {
    conn := Connection{
        Hostname: "localhost",
        Port:     4493,
        Auth:     "root:password?auth=88su",
    }
    jsonBytes, err := json.Marshal(conn)
    if err != nil {
        fmt.Println("Error encoding JSON:", err)
        return
    }
    fmt.Println(string(jsonBytes))
}

In this example, we create a custom MarshalJSON method for the “Connection” struct to format the JSON string into our desired output.

Method 3: Using External Libraries

If you do not feel like implementing a custom format, you can take advantage of third-party packages that comes with additional features.

For example, you can use the pretty package with the following provided link:

https://github.com/tidwall/pretty

Start by installing the package using “go get” as follows:

$ go get -u github.com/tidwall/pretty

Once installed, we can use the Pretty() method to perform the JSON pretty printing as follows:

jsonStr := `{"hostname":"localhost","port":4493,"auth":"root:password?auth=88su"}`
prettyJSON := pretty.Pretty([]byte(jsonStr))
fmt.Println(string(prettyJSON))

This should format the JSON string into a pretty output.

Conclusion

In this comprehensive tutorial, we learned all about the Golang JSON functionality. We covered about marshalling and unmarshalling the JSON data and more. We finally explored all the methods of pretty printing the JSON data in Go such as custom formatting using the “MarshalIndent” function and more.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list