如何使用Go漂亮打印JSON?

时间:2013-09-26 20:59:04

标签: json go pretty-print

有没有人知道在Go中使用漂亮的JSON输出的简单方法?

库存http://golang.org/pkg/encoding/json/包似乎不包含此的功能(编辑:它确实如此,请参阅已接受的答案)并且快速谷歌没有显示任何明显的内容。

我正在寻找的用途是非常打印json.Marshal的结果,只是从任何地方格式化一个充满JSON的字符串,因此为了调试目的,它更容易阅读。

10 个答案:

答案 0 :(得分:222)

通过漂亮的印刷,我认为你的意思是缩进,就像这样

{
    "data": 1234
}

而不是

{"data":1234}

最简单的方法是使用MarshalIndent,它可以指定您希望通过indent参数缩进的方式。因此,json.MarshalIndent(data, "", " ")将使用四个空格进行漂亮打印。

答案 1 :(得分:58)

如果您有一个想要变成JSON的对象,那么接受的答案很棒。这个问题还提到了打印任何JSON字符串,这就是我想要做的事情。我只是想从POST请求(特别是CSP violation report)中记录一些JSON。

要使用MarshalIndent,您必须Unmarshal进入对象。如果你需要它,那就去吧,但我没有。如果你只需要打印一个字节数组,那么普通Indent就是你的朋友。

这是我最终的结果:

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()))
}

答案 2 :(得分:13)

编辑回顾过去,这是非惯用的Go。像这样的小辅助函数增加了额外的复杂步骤。一般来说,Go哲学更喜欢将3条简单的线条包含在1条棘手的线条上。


正如@robyoder所说,json.Indent是要走的路。我以为我添加了这个小prettyprint函数:

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/#/R4LWpkkHINhttp://play.golang.org/p/R4LWpkkHIN

答案 3 :(得分:10)

由于缺乏快速,高质量的方法将JSON编组到Go中的彩色字符串,所以我编写了自己的Marshaller ColorJSON

有了它,您可以使用非常少的代码轻松生成这样的输出:

ColorJSON sample output

package main

import (
    "fmt"
    "github.com/TylerBrock/colorjson"
    "encoding/json"
)

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))
}

我现在正在为它编写文档,但我很高兴分享我的解决方案。

答案 4 :(得分:5)

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
}

答案 5 :(得分:3)

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

答案 6 :(得分:2)

Go中一款简单易用的漂亮打印机。可以通过以下方式将其编译为二进制文件:

go build -o jsonformat jsonformat.go

它从标准输入读取,写入标准输出并允许设置缩进:

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)
    }
}

它允许运行bash命令,例如:

cat myfile | jsonformat | grep "key"

答案 7 :(得分:0)

我有点新意,但这是我到目前为止的收获:

awk -vFPAT="([^ ]*)|('[^']*')" -vOFS=' ' "\$2~/[;' ]foobar[;' ]/" input.txt

这是函数的执行,只是标准的

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
}

代码:

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

答案 8 :(得分:0)

//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))
}

答案 9 :(得分:0)

另一个带有 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)
}

输出

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

Go Playground