Как я могу pretty-print JSON с помощью Go?
кто-нибудь знает простой способ довольно-печати вывода JSON в Go?
запас http://golang.org/pkg/encoding/json/ пакет, похоже, не включает функциональность для этого (EDIT: это так, см. принятый ответ), и быстрый google не обнаруживает ничего очевидного.
использует Я ищу оба довольно-печать результата json.Marshal
и просто форматирование строки, полной JSON, откуда угодно, поэтому ее легче читать для отладки цели.
8 ответов:
под pretty-print, я полагаю, вы имеете в виду отступ, вот так
{ "data": 1234 }
, а не
{"data":1234}
самый простой способ сделать это с
MarshalIndent
, что позволит вам указать, как вы хотели бы его отступ через
принятый ответ Отлично подходит, если у вас есть объект, который вы хотите превратить в JSON. В вопросе также упоминается довольно-печать только любой строки JSON, и это то, что я пытался сделать. Я просто хотел красиво войти в JSON из запроса POST (в частности, a отчет о нарушении 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 parse error: ", error) App.BadRequest(w) return } log.Println("CSP Violation:", string(prettyJSON.Bytes())) }
для лучшего использования памяти, я думаю, это лучше:
var out io.Writer enc := json.NewEncoder(out) enc.SetIndent("", " ") if err := enc.Encode(data); err != nil { panic(err) }
Edit оглядываясь назад, это неидиоматический 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
Я был разочарован отсутствием быстрого, высококачественного способа маршалировать JSON в раскрашенную строку в Go, поэтому я написал свой собственный Маршалл под названием 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)) }
Я пишу документацию для него сейчас, но я был рад поделиться своим решением.
вот что я использую. Если он не может довольно распечатать JSON, он просто возвращает исходную строку. Полезно для печати HTTP-ответов, которые должны содержать 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() }
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 }
простой с полки довольно принтер в 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"