368

Does anyone know of a simple way to pretty-print JSON output in Go?

I'd like to pretty-print the result of json.Marshal, as well as formatting an existing string of JSON so it's easier to read.

Hymns For Disco
8,4952 gold badges26 silver badges42 bronze badges
asked Sep 26, 2013 at 20:59
2
  • Warning: on my experiments, in JSON dictionaries the strings indices must be enclosed in parentheses. So, {name: "value"} won't be okay, despite that most Javascript interpreter uses it. Only {"name": "value"} will work with the Go JSON library functions. Commented Aug 16, 2017 at 19:18
  • 5
    @peterh I think you're confusing JavaScript literal syntax with JSON proper. The JSON spec (json.org) clearly indicates that only string literals are allowed (meaning it needs quotes), while JS language object syntax does not have that restriction. The Go library is following the spec. Commented Aug 16, 2017 at 19:23

16 Answers 16

532

MarshalIndent will allow you to output your JSON with indentation and spacing. For example:

{
 "data": 1234
}

The indent argument specifies the series of characters to indent with. Thus, json.MarshalIndent(data, "", " ") will pretty-print using four spaces for indentation.

Hymns For Disco
8,4952 gold badges26 silver badges42 bronze badges
answered Sep 26, 2013 at 21:17
Sign up to request clarification or add additional context in comments.

2 Comments

Yeah, that looks like just the thing - it's already built-in, only left is to include the keyword "pretty-print" in the pkg doc so the next guy searching finds it. (Will leave a feedback note for the doc maintainers.) Tks!
In case you're trying to print this json to console: MarshalIndent returns a ([]byte, error). Just pass the []byte to string() and print, e.g. j, _ := json.MarshalIndent(data, "", "🐱"); fmt.Println(string(j))
208

The accepted answer is great if you have an object you want to turn into JSON. The question also mentions pretty-printing just any JSON string, and that's what I was trying to do. I just wanted to pretty-log some JSON from a POST request (specifically a CSP violation report).

To use MarshalIndent, you would have to Unmarshal that into an object. If you need that, go for it, but I didn't. If you just need to pretty-print a byte array, plain Indent is your friend.

Here's what I ended up with:

import (
 "bytes"
 "encoding/json"
 "log"
 "net/http"
)
func HandleCSPViolationRequest(w http.ResponseWriter, req *http.Request) {
 body := App.MustReadBody(req, w)
 if body == nil {
 return
 }
 var prettyJSON bytes.Buffer
 error := json.Indent(&prettyJSON, body, "", "\t")
 if error != nil {
 log.Println("JSON parse error: ", error)
 App.BadRequest(w)
 return
 }
 log.Println("CSP Violation:", string(prettyJSON.Bytes()))
}
answered Mar 14, 2015 at 8:26

3 Comments

Thanks! This was very helpful. Just one minor comment that instead of string(prettyJSON.Bytes()) you can do prettyJSON.String()
Cool, didn't know this exists! Perfect for low-impact debug logging.
@Cassio Good point. Actually, we can just do &prettyJSON, because log or fmt executes prettyJSON.String() internally.
69

For better memory usage, I guess this is better:

var out io.Writer
enc := json.NewEncoder(out)
enc.SetIndent("", " ")
if err := enc.Encode(data); err != nil {
 panic(err)
}
answered Feb 23, 2017 at 21:52

4 Comments

Did SetIndent get added recently? It's essentially unknown to most.
@chappjc SetIndent (originally named Indent) was apparently added March 2016 and released in Go 1.7, which was about 3 years after this question was originally asked: github.com/golang/go/commit/… github.com/golang/go/commit/…
Any memory comparisons between this and the usage of json.MarshalIndent(..) ?
@ChenA. this does not really appear needed. Both implementation are pretty clear about their pros and cons. For any object, which has size in memory > the length of the buffer used to stream marshal it, a stream encoder will consume less memory than a non stream-encoder. That last encoder needs to hold both representaton of the same data in memory, the original and its encoded version.
39

I was frustrated by the lack of a fast, high quality way to marshal JSON to a colorized string in Go so I wrote my own Marshaller called ColorJSON.

With it, you can easily produce output like this using very little code:

ColorJSON sample output

package main
import (
 "fmt"
 "encoding/json"
 "github.com/TylerBrock/colorjson"
)
func main() {
 str := `{
 "str": "foo",
 "num": 100,
 "bool": false,
 "null": null,
 "array": ["foo", "bar", "baz"],
 "obj": { "a": 1, "b": 2 }
 }`
 var obj map[string]interface{}
 json.Unmarshal([]byte(str), &obj)
 // Make a custom formatter with indent set
 f := colorjson.NewFormatter()
 f.Indent = 4
 // Marshall the Colorized JSON
 s, _ := f.Marshal(obj)
 fmt.Println(string(s))
}

I'm writing the documentation for it now but I was excited to share my solution.

Oliver
13.2k3 gold badges38 silver badges44 bronze badges
answered May 27, 2018 at 6:56

1 Comment

Thank you very much! Very cool package, used it for my commercial needs!
27

Edit Looking back, this is non-idiomatic Go. Small helper functions like this add an extra step of complexity. In general, the Go philosophy prefers to include the 3 simple lines over 1 tricky line.


As @robyoder mentioned, json.Indent is the way to go. Thought I'd add this small prettyprint function:

package main
import (
 "bytes"
 "encoding/json"
 "fmt"
)
//dont do this, see above edit
func prettyprint(b []byte) ([]byte, error) {
 var out bytes.Buffer
 err := json.Indent(&out, b, "", " ")
 return out.Bytes(), err
}
func main() {
 b := []byte(`{"hello": "123"}`)
 b, _ = prettyprint(b)
 fmt.Printf("%s", b)
}

https://go-sandbox.com/#/R4LWpkkHIN or http://play.golang.org/p/R4LWpkkHIN

answered Apr 16, 2015 at 3:36

Comments

17

Here's what I use. If it fails to pretty print the JSON it just returns the original string. Useful for printing HTTP responses that should contain JSON.

import (
 "encoding/json"
 "bytes"
)
func jsonPrettyPrint(in string) string {
 var out bytes.Buffer
 err := json.Indent(&out, []byte(in), "", "\t")
 if err != nil {
 return in
 }
 return out.String()
}
answered Apr 11, 2016 at 9:13

Comments

8
package cube
import (
 "encoding/json"
 "fmt"
 "github.com/magiconair/properties/assert"
 "k8s.io/api/rbac/v1beta1"
 v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 "testing"
)
func TestRole(t *testing.T) {
 clusterRoleBind := &v1beta1.ClusterRoleBinding{
 ObjectMeta: v1.ObjectMeta{
 Name: "serviceaccounts-cluster-admin",
 },
 RoleRef: v1beta1.RoleRef{
 APIGroup: "rbac.authorization.k8s.io",
 Kind: "ClusterRole",
 Name: "cluster-admin",
 },
 Subjects: []v1beta1.Subject{{
 Kind: "Group",
 APIGroup: "rbac.authorization.k8s.io",
 Name: "system:serviceaccounts",
 },
 },
 }
 b, err := json.MarshalIndent(clusterRoleBind, "", " ")
 assert.Equal(t, nil, err)
 fmt.Println(string(b))
}

How it looks like

SamuelTJackson
1,5374 gold badges21 silver badges46 bronze badges
answered Apr 5, 2020 at 16:27

Comments

6

Here is my solution:

import (
 "bytes"
 "encoding/json"
)
const (
 empty = ""
 tab = "\t"
)
func PrettyJson(data interface{}) (string, error) {
 buffer := new(bytes.Buffer)
 encoder := json.NewEncoder(buffer)
 encoder.SetIndent(empty, tab)
 err := encoder.Encode(data)
 if err != nil {
 return empty, err
 }
 return buffer.String(), nil
}
Nathan Tuggy
2,23827 gold badges33 silver badges38 bronze badges
answered Jun 4, 2017 at 23:55

Comments

5
//You can do it with json.MarshalIndent(data, "", " ")
package main
import(
 "fmt"
 "encoding/json" //Import package
)
//Create struct
type Users struct {
 ID int
 NAME string
}
//Asign struct
var user []Users
func main() {
 //Append data to variable user
 user = append(user, Users{1, "Saturn Rings"})
 //Use json package the blank spaces are for the indent
 data, _ := json.MarshalIndent(user, "", " ")
 //Print json formatted
 fmt.Println(string(data))
}
answered Nov 15, 2019 at 21:47

Comments

4

Another example with http.ResponseWriter.

import (
 "encoding/json"
 "net/http"
)
func main() {
 var w http.ResponseWriter
 type About struct {
 ProgName string
 Version string
 }
 goObj := About{ProgName: "demo", Version: "0.0.0"}
 beautifulJsonByte, err := json.MarshalIndent(goObj, "", " ")
 if err != nil {
 panic(err)
 }
 _, _ = w.Write(beautifulJsonByte)
}

output

{
 "ProgName": "demo",
 "Version": "0.0.0"
}

Go Playground

answered Apr 13, 2021 at 9:45

Comments

4

If you want to create a commandline utility to pretty print JSON


package main
import ("fmt"
 "encoding/json"
 "os"
 "bufio"
 "bytes"
)
func main(){
 var out bytes.Buffer
 reader := bufio.NewReader(os.Stdin)
 text, _ := reader.ReadString('\n')
 err := json.Indent(&out, []byte(text), "", " ")
 if err != nil {
 fmt.Println(err)
 }
 fmt.Println(string(out.Bytes()))
}

echo "{\"boo\":\"moo\"}" | go run main.go 

will produce the following output :

{
 "boo": "moo"
}

feel free to build a binary

go build main.go

and drop it in /usr/local/bin

answered Nov 24, 2021 at 14:33

Comments

2

A simple off the shelf pretty printer in Go. One can compile it to a binary through:

go build -o jsonformat jsonformat.go

It reads from standard input, writes to standard output and allow to set indentation:

package main
import (
 "bytes"
 "encoding/json"
 "flag"
 "fmt"
 "io/ioutil"
 "os"
)
func main() {
 indent := flag.String("indent", " ", "indentation string/character for formatter")
 flag.Parse()
 src, err := ioutil.ReadAll(os.Stdin)
 if err != nil {
 fmt.Fprintf(os.Stderr, "problem reading: %s", err)
 os.Exit(1)
 }
 dst := &bytes.Buffer{}
 if err := json.Indent(dst, src, "", *indent); err != nil {
 fmt.Fprintf(os.Stderr, "problem formatting: %s", err)
 os.Exit(1)
 }
 if _, err = dst.WriteTo(os.Stdout); err != nil {
 fmt.Fprintf(os.Stderr, "problem writing: %s", err)
 os.Exit(1)
 }
}

It allows to run a bash commands like:

cat myfile | jsonformat | grep "key"
answered Sep 25, 2018 at 13:49

Comments

1

i am sort of new to go, but this is what i gathered up so far:

package srf
import (
 "bytes"
 "encoding/json"
 "os"
)
func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
 //write data as buffer to json encoder
 buffer := new(bytes.Buffer)
 encoder := json.NewEncoder(buffer)
 encoder.SetIndent("", "\t")
 err := encoder.Encode(data)
 if err != nil {
 return 0, err
 }
 file, err := os.OpenFile(filedir, os.O_RDWR|os.O_CREATE, 0755)
 if err != nil {
 return 0, err
 }
 n, err := file.Write(buffer.Bytes())
 if err != nil {
 return 0, err
 }
 return n, nil
}

This is the execution of the function, and just standard

b, _ := json.MarshalIndent(SomeType, "", "\t")

Code:

package main
import (
 "encoding/json"
 "fmt"
 "io/ioutil"
 "log"
 minerals "./minerals"
 srf "./srf"
)
func main() {
 //array of Test struct
 var SomeType [10]minerals.Test
 //Create 10 units of some random data to write
 for a := 0; a < 10; a++ {
 SomeType[a] = minerals.Test{
 Name: "Rand",
 Id: 123,
 A: "desc",
 Num: 999,
 Link: "somelink",
 People: []string{"John Doe", "Aby Daby"},
 }
 }
 //writes aditional data to existing file, or creates a new file
 n, err := srf.WriteDataToFileAsJSON(SomeType, "test2.json")
 if err != nil {
 log.Fatal(err)
 }
 fmt.Println("srf printed ", n, " bytes to ", "test2.json")
 //overrides previous file
 b, _ := json.MarshalIndent(SomeType, "", "\t")
 ioutil.WriteFile("test.json", b, 0644)
}
answered Jul 24, 2019 at 23:35

Comments

1

Here is a short json-string to json-string conversion example with indent prettyprint without any struct-objects.

 str := `{"a":{"key":"val"}}`
 data := []byte(str)
 empty := []byte{}
 buf := bytes.NewBuffer(empty)
 json.Indent(buf, data, "", " ")
 readBuf, _ := ioutil.ReadAll(buf)
 fmt.Println((string)(readBuf))
answered Mar 9, 2023 at 17:18

Comments

1

It might be niche but for those who want to pretty print a JSON string as inline.

- { "foo": "bar", "buz": 12345 }
+ {"foo":"bar","buz":12345}
- {
- "foo": "bar",
- "buz":
- 12345 }
+ {"foo":"bar","buz":12345}
func PrettyJSONInline(input []byte) ([]byte, error) {
 var js json.RawMessage
 if err := json.Unmarshal(input, &js); err != nil {
 return nil, errors.New("malformed json")
 }
 // To output pretty with indent use `json.MarshalIndent` instead
 return json.Marshal(js)
}
answered Oct 5, 2023 at 9:59

Comments

0

Use json.MarshalIndent with string

This easyPrint function accepts argument data (any type of data) to print it into the intended (pretty) JSON format.

import (
 "encoding/json"
 "log"
)
func easyPrint(data interface{}) {
 manifestJson, _ := json.MarshalIndent(data, "", " ")
 log.Println(string(manifestJson))
}

With name argument.

TODO: make argument name optional.

func easyPrint(data interface{}, name string) {
 manifestJson, _ := json.MarshalIndent(data, "", " ")
 log.Println(name + " ->", string(manifestJson))
}
answered Apr 18, 2022 at 9:26

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.