有没有适用于Golang的jq包装器可以生成易读的JSON输出?

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

Is there a jq wrapper for golang that can produce human readable JSON output?

问题

我正在编写一个 Go 程序(我们称之为 foo),它在标准输出中输出 JSON。

$ ./foo
{"id":"uuid1","name":"John Smith"}{"id":"uuid2","name":"Jane Smith"}

为了使输出更易读,我需要将其通过管道传递给 jq:

$ ./foo | jq .
{
  "id": "uuid1",
  "name": "John Smith"
}
{
  "id": "uuid2",
  "name": "Jane Smith"
}

是否有一种方法可以使用开源的 jq 包装器实现相同的结果?我尝试找到一些包装器,但它们通常是用于过滤 JSON 输入而不是美化 JSON 输出。

英文:

I'm writing a go program (let's call it foo) that outputs JSON on the Standard Out.

$ ./foo
{"id":"uuid1","name":"John Smith"}{"id":"uuid2","name":"Jane Smith"}

In order to make the output human readable, I have to pipe it into jq like:

$ ./foo | jq .

{
"id":"uuid1",
"name": "John Smith"
}
{
"id":"uuid2"
"name": "Jane Smith"
}

Is there a way to achieve the same result using a jq wrapper that is open sourced? I tried finding some but they are usually wrapping the functionality for filtering JSON input not prettifying JSON output.

答案1

得分: 8

encoding/json 包支持开箱即用的漂亮输出。你可以使用 json.MarshalIndent() 函数。或者如果你使用 json.Encoder,则在调用 Encoder.Encode() 之前调用其 Encoder.SetIndent() 方法(自 Go 1.7 起)。

示例:

m := map[string]interface{}{"id": "uuid1", "name": "John Smith"}

data, err := json.MarshalIndent(m, "", "  ")
if err != nil {
    panic(err)
}
fmt.Println(string(data))

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
if err := enc.Encode(m); err != nil {
    panic(err)
}

输出结果(在 Go Playground 上尝试):

{
  "id": "uuid1",
  "name": "John Smith"
}
{
  "id": "uuid1",
  "name": "John Smith"
}

如果你只想格式化一个已经存在的 JSON 文本,你可以使用 json.Indent() 函数:

src := `{"id":"uuid1","name":"John Smith"}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "", "  "); err != nil {
    panic(err)
}
fmt.Println(dst.String())

输出结果(在 Go Playground 上尝试):

{
  "id": "uuid1",
  "name": "John Smith"
}

这两个 indent 函数的前两个参数都是 string 类型:

prefix, indent string

文档中有解释:

> JSON 对象或数组中的每个元素都以新的缩进行开头,该行以 prefix 开始,后面跟随一个或多个 indent 的副本,根据缩进的嵌套级别而定。

因此,每个换行都以 prefix 开始,后面跟随 0 个或多个 indent 的副本,具体取决于嵌套级别。

如果你像这样为它们指定值,就会变得清晰明了:

json.Indent(dst, []byte(src), "+", "-")

使用嵌套对象进行测试:

src := `{"id":"uuid1","name":"John Smith","embedded:":{"fieldx":"y"}}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "+", "-"); err != nil {
    panic(err)
}
fmt.Println(dst.String())

输出结果(在 Go Playground 上尝试):

{
+-"id": "uuid1",
+-"name": "John Smith",
+-"embedded:": {
+--"fieldx": "y"
+-}
+}
英文:

The encoding/json package supports pretty output out-of-the-box. You may use json.MarshalIndent(). Or if you're using json.Encoder, then call its Encoder.SetIndent() (new since Go 1.7) method prior to calling Encoder.Encode().

Examples:

m := map[string]interface{}{"id": "uuid1", "name": "John Smith"}

data, err := json.MarshalIndent(m, "", "  ")
if err != nil {
	panic(err)
}
fmt.Println(string(data))

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
if err := enc.Encode(m); err != nil {
	panic(err)
}

Output (try it on the Go Playground):

{
  "id": "uuid1",
  "name": "John Smith"
}
{
  "id": "uuid1",
  "name": "John Smith"
}

If you just want to format a "ready" JSON text, you may use the json.Indent() function:

src := `{"id":"uuid1","name":"John Smith"}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "", "  "); err != nil {
	panic(err)
}
fmt.Println(dst.String())

Output (try it on the Go Playground):

{
  "id": "uuid1",
  "name": "John Smith"
}

The 2 string parameters to these indent functions are:

prefix, indent string

Explanation is in the docs:

> Each element in a JSON object or array begins on a new, indented line beginning with prefix followed by one or more copies of indent according to the indentation nesting.

So each newline will be started with prefix, which will be followed by 0 or more copies of indent, depending on the nesting level.

It becomes clear and obvious if you specify values for them like this:

json.Indent(dst, []byte(src), "+", "-")

Testing it with embedded objects:

src := `{"id":"uuid1","name":"John Smith","embedded:":{"fieldx":"y"}}`

dst := &bytes.Buffer{}
if err := json.Indent(dst, []byte(src), "+", "-"); err != nil {
	panic(err)
}
fmt.Println(dst.String())

Output (try it on the Go Playground):

{
+-"id": "uuid1",
+-"name": "John Smith",
+-"embedded:": {
+--"fieldx": "y"
+-}
+}

huangapple
  • 本文由 发表于 2017年3月14日 22:00:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/42788045.html
匿名

发表评论

匿名网友

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

确定