我如何使用Go漂亮打印JSON ?

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

我想漂亮地打印json.Marshal的结果,以及格式化现有的JSON字符串,以便更容易阅读。

268011 次浏览

MarshalIndent将允许你输出带有缩进和空格的JSON。例如:

{
"data": 1234
}

indent参数指定要缩进的字符序列。因此,json.MarshalIndent(data, "", " ")将使用四个空格进行缩进。

如果您想将一个对象转换为JSON,那么接受的答案是非常好的。这个问题还提到了漂亮打印任何JSON字符串,这就是我试图做的。我只是想从POST请求(特别是CSP违规报告)漂亮地记录一些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()))
}

回头看,这是非惯用的围棋。像这样的小助手函数增加了额外的复杂性。一般来说,围棋哲学倾向于包含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

这是我用的。如果它不能漂亮地打印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()
}

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

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

这是我的解决方案:

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
}

我对在Go中缺乏快速、高质量的方法将JSON编组为彩色字符串感到沮丧,所以我写了自己的编组器ColorJSON

有了它,你可以用很少的代码轻松生成如下输出:

ColorJSON sample output

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

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

一个简单的货架上漂亮的打印机。可以通过以下方法将其编译为二进制文件:

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"

我是一个新手,但这是我目前为止收集到的:

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

代码:

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)


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

另一个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

如果你想创建一个命令行工具来漂亮地打印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

将产生以下输出:

{
"boo": "moo"
}

请随意构建二进制文件

go build main.go

并将其放到/usr/local/bin

使用json.MarshalIndentstring

easyPrint函数接受参数data(任何类型的数据),并将其打印成预期的(漂亮的)JSON格式。

import (
"encoding/json"
"log"
)


func easyPrint(data interface{}) {
manifestJson, _ := json.MarshalIndent(data, "", "  ")


log.Println(string(manifestJson))
}

name参数。

将参数name设为可选。

func easyPrint(data interface{}, name string) {
manifestJson, _ := json.MarshalIndent(data, "", "  ")


log.Println(name + " ->", string(manifestJson))
}