有没有人知道在Go中使用漂亮的JSON输出的简单方法?
库存http://golang.org/pkg/encoding/json/包似乎不包含此的功能(编辑:它确实如此,请参阅已接受的答案)并且快速谷歌没有显示任何明显的内容。
我正在寻找的用途是非常打印json.Marshal
的结果,只是从任何地方格式化一个充满JSON的字符串,因此为了调试目的,它更容易阅读。
答案 0 :(得分:222)
通过漂亮的印刷,我认为你的意思是缩进,就像这样
{
"data": 1234
}
而不是
{"data":1234}
最简单的方法是使用MarshalIndent
,它可以指定您希望通过indent
参数缩进的方式。因此,json.MarshalIndent(data, "", " ")
将使用四个空格进行漂亮打印。
答案 1 :(得分:58)
如果您有一个想要变成JSON的对象,那么接受的答案很棒。这个问题还提到了打印任何JSON字符串,这就是我想要做的事情。我只是想从POST请求(特别是CSP violation report)中记录一些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()))
}
答案 2 :(得分: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)
}
https://go-sandbox.com/#/R4LWpkkHIN或http://play.golang.org/p/R4LWpkkHIN
答案 3 :(得分:10)
由于缺乏快速,高质量的方法将JSON编组到Go中的彩色字符串,所以我编写了自己的Marshaller ColorJSON。
有了它,您可以使用非常少的代码轻松生成这样的输出:
package main
import (
"fmt"
"github.com/TylerBrock/colorjson"
"encoding/json"
)
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))
}
我现在正在为它编写文档,但我很高兴分享我的解决方案。
答案 4 :(得分: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
}
答案 5 :(得分:3)
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))
}
答案 6 :(得分: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", " ", "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"
答案 7 :(得分:0)
我有点新意,但这是我到目前为止的收获:
awk -vFPAT="([^ ]*)|('[^']*')" -vOFS=' ' "\$2~/[;' ]foobar[;' ]/" input.txt
这是函数的执行,只是标准的
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")
答案 8 :(得分:0)
//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))
}
答案 9 :(得分:0)
另一个带有 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"
}