How can I pretty-print JSON using Go?

后端 未结 11 1599
挽巷
挽巷 2020-12-07 08:12

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

The stock http://golang.org/pkg/encoding/json/ package does not seem to include functiona

相关标签:
11条回答
  • 2020-12-07 08:27

    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.

    0 讨论(0)
  • 2020-12-07 08:31

    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.

    0 讨论(0)
  • 2020-12-07 08:31
    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

    0 讨论(0)
  • 2020-12-07 08:31

    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"
    
    0 讨论(0)
  • 2020-12-07 08:39

    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

    0 讨论(0)
提交回复
热议问题