如何使用Go漂亮打印JSON?

Bra*_*ody 161 json pretty-print go

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

股票http://golang.org/pkg/encoding/json/包似乎没有包含这方面的功能(编辑:它确实,看到接受的答案)和一个快速谷歌没有出现任何明显的东西.

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

Ale*_*uer 253

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

{
    "data": 1234
}
Run Code Online (Sandbox Code Playgroud)

而不是

{"data":1234}
Run Code Online (Sandbox Code Playgroud)

最简单的方法是使用MarshalIndent,这将允许您指定通过indent参数缩进的方式.因此,json.MarshalIndent(data, "", " ")将使用四个空格进行精美打印以进行缩进.

  • json.MarshalIndent(data,“”,“”)`如果您想要猫。_抱歉_ (32认同)
  • `json.MarshalIndent(data,"","\ t")``如果你想要标签. (22认同)
  • 是的,这看起来就像是东西 - 它已经是内置的,只剩下在pkg文档中包含关键字"pretty-print"所以下一个搜索的人找到它.(将为文档维护人员留下反馈说明.)Tks! (14认同)
  • 如果您尝试将此 json 打印到控制台:MarshalIndent 返回 ([]byte, error)。只需将 []byte 传递给 string() 并打印,例如 `j, _ := json.MarshalIndent(data, "", ""); fmt.Println(字符串(j))` (14认同)
  • `json.MarshalIndent(data, "", " ")` 如果你想要.. 间隔猫... *抱歉* (7认同)
  • json.MarshalIndent(data,“”,“ \ t”)`如果您想...虎斑猫... _sorry_ (2认同)

rob*_*der 64

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

要使用MarshalIndent,您必须将Unmarshal其转换为对象.如果你需要它,那就去吧,但我没有.如果你只需要打印一个字节数组,那么plain 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()))
}
Run Code Online (Sandbox Code Playgroud)

  • @Cassio 好点。实际上,我们可以只执行`&prettyJSON`,因为`log`或`fmt`在内部执行`prettyJSON.String()`。 (4认同)
  • 谢谢!这非常有帮助。只是一个小评论,而不是 `string(prettyJSON.Bytes())` 你可以做 `prettyJSON.String()` (2认同)

mh-*_*bon 38

为了更好的内存使用,我想这更好:

var out io.Writer
enc := json.NewEncoder(out)
enc.SetIndent("", "    ")
if err := enc.Encode(data); err != nil {
    panic(err)
}
Run Code Online (Sandbox Code Playgroud)

  • @chappjc `SetIndent`(原名 `Indent`)显然是在 2016 年 3 月添加的,并在 Go 1.7 中发布,这是最初提出这个问题大约 3 年后:https://github.com/golang/go/commit/098b62644f9388a8afba90d3e74ea7d7497def4c https://github.com/golang/go/commit/34b17d4dc5726eebde437f2c1b680d039cc3e7c0 (3认同)

jpi*_*ora 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)
}
Run Code Online (Sandbox Code Playgroud)

https://go-sandbox.com/#/R4LWpkkHINhttp://play.golang.org/p/R4LWpkkHIN


Tyl*_*ock 13

由于缺乏快速,高质量的方法将JSON编组到Go中的彩色字符串,所以我写了一个名为ColorJSON的自己的Marshaller,我感到很沮丧.

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

ColorJSON示例输出

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))
}
Run Code Online (Sandbox Code Playgroud)

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

  • 非常感谢!非常酷的包,用它来满足我的商业需求! (2认同)

Tim*_*mmm 6

这是我使用的.如果它无法完全打印JSON,它只返回原始字符串.用于打印包含JSON的HTTP响应.

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()
}
Run Code Online (Sandbox Code Playgroud)


Rae*_*ali 5

这是我的解决方案:

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
}
Run Code Online (Sandbox Code Playgroud)


Ill*_*lud 5

//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))
}
Run Code Online (Sandbox Code Playgroud)


小智 5

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

Run Code Online (Sandbox Code Playgroud)

看起来如何