4

I'm writing a go program (let's call it foo) that outputs JSON on the Standard Out.

$ ./foo
{"id":"uuid1","name":"John Smith"}{"id":"uuid2","name":"Jane Smith"}

In order to make the output human readable, I have to pipe it into jq like:

$ ./foo | jq .

{
"id":"uuid1",
"name": "John Smith"
}
{
"id":"uuid2"
"name": "Jane Smith"
}

Is there a way to achieve the same result using a jq wrapper that is open sourced? I tried finding some but they are usually wrapping the functionality for filtering JSON input not prettifying JSON output.

3
  • Are you looking for this? stackoverflow.com/questions/19038598/… Commented Mar 14, 2017 at 14:02
  • So, the thing is I have the JSON response in a byte array and the schema of the JSON can vary arbitrarily so I can't necessarily unmarshal it without unnecessary hacks. I just need to print this JSON byte array in a pretty manner. Commented Mar 14, 2017 at 14:11
  • @SiddharthShukla The json package has support for that too: json.Indent(). See my edited answer. Commented Mar 14, 2017 at 14:22

1 Answer 1

9

The encoding/json package supports pretty output out-of-the-box. You may use json.MarshalIndent(). Or if you're using json.Encoder, then call its Encoder.SetIndent() (new since Go 1.7) method prior to calling Encoder.Encode().

Examples:

m := map[string]interface{}{"id": "uuid1", "name": "John Smith"}

data, err := json.MarshalIndent(m, "", "  ")
if err != nil {
    panic(err)
}
fmt.Println(string(data))

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
if err := enc.Encode(m); err != nil {
    panic(err)
}

Output (try it on the Go Playground):

{
  "id": "uuid1",
  "name": "John Smith"
}
{
  "id": "uuid1",
  "name": "John Smith"
}

If you just want to format a "ready" JSON text, you may use the json.Indent() function:

src := `{"id":"uuid1","name":"John Smith"}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "", "  "); err != nil {
    panic(err)
}
fmt.Println(dst.String())

Output (try it on the Go Playground):

{
  "id": "uuid1",
  "name": "John Smith"
}

The 2 string parameters to these indent functions are:

prefix, indent string

Explanation is in the docs:

Each element in a JSON object or array begins on a new, indented line beginning with prefix followed by one or more copies of indent according to the indentation nesting.

So each newline will be started with prefix, which will be followed by 0 or more copies of indent, depending on the nesting level.

It becomes clear and obvious if you specify values for them like this:

json.Indent(dst, []byte(src), "+", "-")

Testing it with embedded objects:

src := `{"id":"uuid1","name":"John Smith","embedded:":{"fieldx":"y"}}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "+", "-"); err != nil {
    panic(err)
}
fmt.Println(dst.String())

Output (try it on the Go Playground):

{
+-"id": "uuid1",
+-"name": "John Smith",
+-"embedded:": {
+--"fieldx": "y"
+-}
+}
Sign up to request clarification or add additional context in comments.

1 Comment

Is there any way to have lists of basic types not linebreaked?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.