web-dev-qa-db-ja.com

Goを使用してJSONをきれいに印刷するにはどうすればよいですか?

GoでJSON出力をきれいに印刷する簡単な方法を知っている人はいますか?

在庫 http://golang.org/pkg/encoding/json/ パッケージにはこの機能が含まれていないようです (編集:あります、受け入れられた答えを参照してください)そして、速いグーグルは明白な何かを見せません。

私が探している用途は、json.Marshalの結果をきれいに表示することと、どこからでもJSONで満たされた文字列をフォーマットするだけであるため、デバッグ目的で読みやすくなります。

143
Brad Peabody

プリティプリントとは、インデントされていることを意味すると思います

{
    "data": 1234
}

のではなく

{"data":1234}

これを行う最も簡単な方法は MarshalIndent を使用することです。これにより、indent引数を使用してインデントする方法を指定できます。したがって、json.MarshalIndent(data, "", " ")はインデントに4つのスペースを使用してきれいに印刷します。

224
Alexander Bauer

JSONに変換したいオブジェクトがある場合、受け入れられる答えは素晴らしいです。質問では、JSON文字列だけをきれいに印刷することにも言及していますが、それが私がやろうとしていたことです。 POSTリクエスト(具体的には CSP違反レポート )から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()))
}
58
robyoder

より良いメモリ使用量のために、私はこれがより良いと思います:

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

Edit振り返ってみると、これは非慣用的なGoです。このような小さなヘルパー関数は、さらに複雑なステップを追加します。一般に、Goの哲学は、1つのトリッキーな行よりも3つのシンプルな行を含めることを好みます。


@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

13
jpillora

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

私は今、そのためのドキュメントを書いていますが、私のソリューションを共有することに興奮しました。

10
Tyler Brock

これが私の解決策です

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
Raed Shomali

これが私が使用するものです。 JSONをきれいに印刷できない場合は、元の文字列を返すだけです。 should 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()
}
5
Timmmm

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"
2
Paweł Szczur

私は行くのは新しいですが、これは私がこれまでにまとめたものです:

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)

}
1
accnameowl