你可以使用Go语言来漂亮地打印JSON。

huangapple go评论149阅读模式
英文:

How can I pretty-print JSON using Go?

问题

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

我想要漂亮打印json.Marshal的结果,同时也想要格式化一个已有的JSON字符串,使其更易读。

英文:

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

I'd like to pretty-print the result of json.Marshal, as well as formatting an existing string of JSON so it's easier to read.

答案1

得分: 495

MarshalIndent函数可以让你以缩进和空格的形式输出JSON。例如:

{
    "data": 1234
}

indent参数指定了缩进的字符序列。因此,使用json.MarshalIndent(data, "", " ")将使用四个空格进行漂亮的打印输出。

英文:

MarshalIndent will allow you to output your JSON with indentation and spacing. For example:

{
    "data": 1234
}

The indent argument specifies the series of characters to indent with. Thus, json.MarshalIndent(data, "", " ") will pretty-print using four spaces for indentation.

答案2

得分: 185

接受的答案非常好,如果你有一个想要转换为JSON的对象,那么可以使用这个答案。问题还提到了对任何JSON字符串进行漂亮打印,这正是我想要做的。我只是想要从POST请求中漂亮地记录一些JSON(特别是CSP违规报告)。

要使用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解析错误:", error)
		App.BadRequest(w)
		return
	}

	log.Println("CSP违规:", string(prettyJSON.Bytes()))
}
英文:

The accepted answer is great if you have an object you want to turn into JSON. The question also mentions pretty-printing just any JSON string, and that's what I was trying to do. I just wanted to pretty-log some JSON from a POST request (specifically a CSP violation report).

To use MarshalIndent, you would have to Unmarshal that into an object. If you need that, go for it, but I didn't. If you just need to pretty-print a byte array, plain Indent is your friend.

Here's what I ended up with:

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

得分: 63

为了更好地利用内存,我认为以下代码更好:

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

这段代码使用了json包中的NewEncoder函数来创建一个编码器enc,然后通过enc.SetIndent方法设置了缩进格式。最后,使用enc.Encode方法将数据data编码并写入out中,如果出现错误则会触发panic

英文:

For better memory usage, I guess this is better:

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

答案4

得分: 36

我对Go语言中缺乏一种快速、高质量的方法将JSON编组为带有颜色的字符串感到沮丧,所以我编写了自己的编组器,名为ColorJSON

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

你可以使用Go语言来漂亮地打印JSON。

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)

    // 使用设置了缩进的自定义格式化器
    f := colorjson.NewFormatter()
    f.Indent = 4

    // 编组带有颜色的JSON
    s, _ := f.Marshal(obj)
    fmt.Println(string(s))
}

我正在撰写相关文档,但我很高兴能分享我的解决方案。

英文:

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:

你可以使用Go语言来漂亮地打印JSON。

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.

答案5

得分: 27

编辑 回顾一下,这段代码不符合 Go 的惯用写法。像这样的小助手函数会增加额外的复杂性。一般来说,Go 的哲学更喜欢使用三行简单的代码而不是一个复杂的代码行。


正如 @robyoder 提到的,json.Indent 是一个不错的选择。我想添加这个小的 prettyprint 函数:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
)

// 不要这样做,请参考上面的编辑
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 或者 http://play.golang.org/p/R4LWpkkHIN

英文:

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

答案6

得分: 16

以下是我翻译好的内容:

这是我使用的代码。如果无法对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()
}
英文:

Here's what I use. If it fails to pretty print the JSON it just returns the original string. Useful for printing HTTP responses that should contain JSON.

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

答案7

得分: 7

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

你可以使用Go语言来漂亮地打印JSON。

英文:
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))
}

你可以使用Go语言来漂亮地打印JSON。

答案8

得分: 6

以下是您要翻译的内容:

这是我的解决方案:

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
}
英文:

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
}

答案9

得分: 5

你好!以下是代码的中文翻译:

// 你可以使用json.MarshalIndent(data, "", "  ")来实现

package main

import (
	"fmt"
	"encoding/json" // 导入包
)

// 创建结构体
type Users struct {
	ID   int
	NAME string
}

// 分配结构体
var user []Users

func main() {
	// 将数据追加到变量user中
	user = append(user, Users{1, "Saturn Rings"})
	// 使用json包进行格式化,空格用于缩进
	data, _ := json.MarshalIndent(user, "", "  ")
	// 打印格式化后的json
	fmt.Println(string(data))
}

希望对你有帮助!如果有任何其他问题,请随时提问。

英文:
//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))
}

答案10

得分: 4

使用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语言来漂亮地打印JSON。

英文:

Another example with 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)
}

output

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

你可以使用Go语言来漂亮地打印JSON。

答案11

得分: 3

如果你想创建一个命令行实用程序来美化打印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目录下。

英文:

If you want to create a commandline utility to pretty print 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 

will produce the following output :

{
  "boo": "moo"
}

feel free to build a binary

go build main.go

and drop it in /usr/local/bin

答案12

得分: 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", "  ", "格式化时的缩进字符串/字符")
	flag.Parse()
	src, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		fmt.Fprintf(os.Stderr, "读取出错:%s", err)
		os.Exit(1)
	}

	dst := &bytes.Buffer{}
	if err := json.Indent(dst, src, "", *indent); err != nil {
		fmt.Fprintf(os.Stderr, "格式化出错:%s", err)
		os.Exit(1)
	}
	if _, err = dst.WriteTo(os.Stdout); err != nil {
		fmt.Fprintf(os.Stderr, "写入出错:%s", err)
		os.Exit(1)
	}
}

它允许运行类似以下的bash命令:

cat myfile | jsonformat | grep "key"
英文:

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"

答案13

得分: 1

我对Go语言还比较新,但是我已经整理了一些信息:

package srf

import (
	"bytes"
	"encoding/json"
	"os"
)

func WriteDataToFileAsJSON(data interface{}, filedir string) (int, error) {
	//将数据写入缓冲区并使用JSON编码器进行编码
	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() {

	//Test结构体的数组
	var SomeType [10]minerals.Test

	//创建10个随机数据单元进行写入
	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"},
		}
	}

	//将附加数据写入现有文件,如果文件不存在则创建新文件
	n, err := srf.WriteDataToFileAsJSON(SomeType, "test2.json")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("srf printed ", n, " bytes to ", "test2.json")

	//覆盖之前的文件
	b, _ := json.MarshalIndent(SomeType, "", "\t")
	ioutil.WriteFile("test.json", b, 0644)

}
英文:

i am sort of new to go, but this is what i gathered up so far:

package srf

import (
	&quot;bytes&quot;
	&quot;encoding/json&quot;
	&quot;os&quot;
)

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(&quot;&quot;, &quot;\t&quot;)

	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
}

This is the execution of the function, and just standard

b, _ := json.MarshalIndent(SomeType, &quot;&quot;, &quot;\t&quot;)

Code:

package main

import (
	&quot;encoding/json&quot;
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;

	minerals &quot;./minerals&quot;
	srf &quot;./srf&quot;
)

func main() {

	//array of Test struct
	var SomeType [10]minerals.Test

	//Create 10 units of some random data to write
	for a := 0; a &lt; 10; a++ {
		SomeType[a] = minerals.Test{
			Name:   &quot;Rand&quot;,
			Id:     123,
			A:      &quot;desc&quot;,
			Num:    999,
			Link:   &quot;somelink&quot;,
			People: []string{&quot;John Doe&quot;, &quot;Aby Daby&quot;},
		}
	}

	//writes aditional data to existing file, or creates a new file
	n, err := srf.WriteDataToFileAsJSON(SomeType, &quot;test2.json&quot;)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(&quot;srf printed &quot;, n, &quot; bytes to &quot;, &quot;test2.json&quot;)
	
	//overrides previous file
	b, _ := json.MarshalIndent(SomeType, &quot;&quot;, &quot;\t&quot;)
	ioutil.WriteFile(&quot;test.json&quot;, b, 0644)

}

答案14

得分: 1

这是一个简短的JSON字符串到JSON字符串转换的示例,带有漂亮的缩进打印,没有任何结构对象。

	str := `{&quot;a&quot;:{&quot;key&quot;:&quot;val&quot;}}`
	data := []byte(str)
	empty := []byte{}
	buf := bytes.NewBuffer(empty)
	json.Indent(buf, data, &quot;&quot;, &quot;    &quot;)
	readBuf, _ := ioutil.ReadAll(buf)
	fmt.Println((string)(readBuf))

这段代码演示了如何将一个JSON字符串转换为另一个JSON字符串,并使用缩进进行漂亮的打印输出,没有使用任何结构对象。

英文:

Here is a short json-string to json-string conversion example with indent prettyprint without any struct-objects.

	str := `{&quot;a&quot;:{&quot;key&quot;:&quot;val&quot;}}`
	data := []byte(str)
	empty := []byte{}
	buf := bytes.NewBuffer(empty)
	json.Indent(buf, data, &quot;&quot;, &quot;    &quot;)
	readBuf, _ := ioutil.ReadAll(buf)
	fmt.Println((string)(readBuf))

答案15

得分: 0

使用json.MarshalIndentstring

这个easyPrint函数接受一个data参数(任意类型的数据),将其以预期的(漂亮的)JSON格式打印出来。

import (
  "encoding/json"
  "log"
)

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

  log.Println(string(manifestJson))
}

带有name参数。

TODO: 使name参数可选。

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

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

Use json.MarshalIndent with string

This easyPrint function accepts argument data (any type of data) to print it into the intended (pretty) JSON format.

import (
  &quot;encoding/json&quot;
  &quot;log&quot;
)

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

  log.Println(string(manifestJson))
}

With name argument.

TODO: make argument name optional.

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

  log.Println(name + &quot; -&gt;&quot;, string(manifestJson))
}

huangapple
  • 本文由 发表于 2013年9月27日 04:59:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/19038598.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定