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.
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.
j, _ := json.MarshalIndent(data, "", "🐱"); fmt.Println(string(j))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()))
}
string(prettyJSON.Bytes()) you can do prettyJSON.String()&prettyJSON, because log or fmt executes prettyJSON.String() internally.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)
}
SetIndent get added recently? It's essentially unknown to most.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/…json.MarshalIndent(..) ?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.
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
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()
}
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))
}

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
}
//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))
}
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"
}
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
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"
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)
}
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))
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)
}
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))
}
{name: "value"}won't be okay, despite that most Javascript interpreter uses it. Only{"name": "value"}will work with the Go JSON library functions.