Как я могу pretty-print JSON с помощью Go?

кто-нибудь знает простой способ pretty-print вывода 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 (в частности,отчет о нарушении CSP).

использовать MarshalIndent, вам придется Unmarshal это в объект. Если тебе это нужно, действуй, но не я. Если вам просто нужно pretty-print массив байтов, простой 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)
}

редактировать оглядываясь назад, это не идиоматический 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.

С его помощью вы можете легко производить вывод, как это, используя очень мало кода:

ColorJSON sample output

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"