【问题标题】:How can I pretty-print JSON using Go?如何使用 Go 漂亮地打印 JSON?
【发布时间】:2013-10-03 00:47:38
【问题描述】:

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

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

我正在寻找的用途既可以漂亮地打印 json.Marshal 的结果,也可以从任何地方格式化一个充满 JSON 的字符串,因此更易于阅读以进行调试。

【问题讨论】:

  • 警告:在我的实验中,在 JSON 字典中,字符串索引必须括在括号中。所以,{name: "value"} 不行,尽管大多数 Javascript 解释器都使用它 {"name": "value"} 将与 Go JSON 库函数一起使用。
  • @peterh 我认为您将 JavaScript 文字语法与 JSON 本身混淆了。 JSON 规范 (json.org) 明确指出只允许使用字符串文字(这意味着它需要引号),而 JS 语言对象语法没有这个限制。 Go 库遵循规范。

标签: json go pretty-print


【解决方案1】:
推荐的答案 Go Language

通过漂亮的打印,我假设你的意思是缩进,像这样

{
    "data": 1234
}

而不是

{"data":1234}

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

【讨论】:

  • 是的,看起来就是这样——它已经内置了,只剩下在 pkg 文档中包含关键字“pretty-print”,以便下一个搜索的人找到它。 (将为文档维护者留下反馈说明。)谢谢!
  • json.MarshalIndent(data, "", "\t") 如果你想要标签。
  • json.MarshalIndent(data, "", "\t?") 如果你想要...虎斑猫... 对不起
  • json.MarshalIndent(data, "", " ?") 如果你想要 .... 间隔猫... 对不起
  • 如果您尝试将此 json 打印到控制台:MarshalIndent 返回 ([]byte, error)。只需将 []byte 传递给 string() 并打印,例如j, _ := json.MarshalIndent(data, "", "?"); fmt.Println(string(j))
【解决方案2】:

如果您有一个想要转换为 JSON 的对象,那么接受的答案是很好的。该问题还提到漂亮打印任何 JSON 字符串,这就是我想要做的。我只是想从 POST 请求(特别是 CSP violation report)中漂亮地记录一些 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()))
}

【讨论】:

  • 谢谢!这很有帮助。只是一个小评论,而不是string(prettyJSON.Bytes()) 你可以做prettyJSON.String()
【解决方案3】:

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

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

【讨论】:

  • 最近添加了SetIndent 吗?大多数人基本上都不知道它。
  • @chappjc SetIndent(最初名为Indent)显然是在2016年3月添加并在Go 1.7中发布的,大约在这个问题最初提出3年后:github.com/golang/go/commit/…github.com/golang/go/commit/…
  • 这个和json.MarshalIndent(..)的使用有什么内存比较吗?
  • @ChenA。这似乎并不需要。两种实现都非常清楚它们的优缺点。对于任何在内存中的大小 > 用于流式编组它的缓冲区长度的对象,流编码器将比非流编码器消耗更少的内存。最后一个编码器需要在内存中保存相同数据的表示形式,即原始版本及其编码版本。
【解决方案4】:

我对在 Go 中将 JSON 编组为彩色字符串缺乏快速、高质量的方法感到沮丧,因此我编写了自己的 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))
}

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

【讨论】:

  • 非常感谢!非常酷的包,用于我的商业需求!
【解决方案5】:

编辑 回过头来看,这不是惯用的 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

【讨论】:

    【解决方案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()
    }
    

    【讨论】:

      【解决方案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))
      }
      
      

      【讨论】:

        【解决方案8】:

        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】:
          //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】:

            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"
            

            【讨论】:

              【解决方案11】:

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

              【讨论】:

                【解决方案12】:

                我有点新手,但这是我到目前为止收集的内容:

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

                【讨论】:

                  【解决方案13】:

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

                  【讨论】:

                    猜你喜欢
                    • 2011-08-05
                    • 2015-07-03
                    • 2015-08-26
                    相关资源
                    最近更新 更多