英文:
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。
使用它,你可以使用很少的代码轻松生成如下输出:
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:
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))
}
英文:
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
得分: 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
}
英文:
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"
}
英文:
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"
}
答案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 (
"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
}
This is the execution of the function, and just standard
b, _ := json.MarshalIndent(SomeType, "", "\t")
Code:
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)
}
答案14
得分: 1
这是一个简短的JSON字符串到JSON字符串转换的示例,带有漂亮的缩进打印,没有任何结构对象。
str := `{"a":{"key":"val"}}`
data := []byte(str)
empty := []byte{}
buf := bytes.NewBuffer(empty)
json.Indent(buf, data, "", " ")
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 := `{"a":{"key":"val"}}`
data := []byte(str)
empty := []byte{}
buf := bytes.NewBuffer(empty)
json.Indent(buf, data, "", " ")
readBuf, _ := ioutil.ReadAll(buf)
fmt.Println((string)(readBuf))
答案15
得分: 0
使用json.MarshalIndent
和string
这个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 (
"encoding/json"
"log"
)
func easyPrint(data interface{}) {
manifestJson, _ := json.MarshalIndent(data, "", " ")
log.Println(string(manifestJson))
}
With name
argument.
TODO: make argument name
optional.
func easyPrint(data interface{}, name string) {
manifestJson, _ := json.MarshalIndent(data, "", " ")
log.Println(name + " ->", string(manifestJson))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论