How can I pretty-print JSON using Go?
By pretty-print, I assume you mean indented, like so
{
"data": 1234
}
rather than
{"data":1234}
The easiest way to do this is with MarshalIndent
, which will let you specify how you would like it indented via the indent
argument. Thus, json.MarshalIndent(data, "", " ")
will pretty-print using four spaces for indentation.
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()))
}
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:
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.
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)
}