it-swarm.com.de

Wie kann ich JSON mit Go hübsch drucken?

Kennt jemand eine einfache Möglichkeit, JSON-Ausgaben in Go hübsch zu drucken?

Das Paket stock http://golang.org/pkg/encoding/json/ scheint hierfür keine Funktionalität zu enthalten (BEARBEITEN: das stimmt, siehe akzeptierte Antwort) und eine schnelle Google-Suche zeigt nichts Offensichtliches.

Von mir gesuchte Anwendungen sind beide das Ergebnis von json.Marshal und formatieren Sie einfach eine Zeichenfolge mit JSON von jedem beliebigen Ort aus, damit das Lesen für Debug-Zwecke einfacher ist.

148
Brad Peabody

Mit hübschem Druck meine ich wohl eingerückt

{
    "data": 1234
}

eher, als

{"data":1234}

Am einfachsten geht das mit MarshalIndent , mit dem Sie angeben können, wie es über das Argument indent eingerückt werden soll. Daher wird json.MarshalIndent(data, "", " ") mit vier Leerzeichen für den Einzug hübsch gedruckt.

233
Alexander Bauer

Die akzeptierte Antwort ist großartig, wenn Sie ein Objekt haben, das Sie in JSON verwandeln möchten. In der Frage wird auch erwähnt, dass nur eine beliebige JSON-Zeichenfolge hübsch gedruckt wird, und genau das habe ich versucht. Ich wollte nur einige JSON-Dateien aus einer POST Anfrage (speziell ein CSP-Verstoß-Bericht ) hübsch protokollieren.

Um MarshalIndent zu verwenden, müssten Sie das Unmarshal in ein Objekt einfügen. Wenn Sie das brauchen, versuchen Sie es, aber ich habe es nicht getan. Wenn Sie nur ein Byte-Array hübsch drucken müssen, ist plain Indent Ihr Freund.

Folgendes ist mir eingefallen:

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()))
}
60
robyoder

Für eine bessere Speichernutzung ist dies wahrscheinlich besser:

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

Bearbeiten Rückblickend ist dies nicht idiomatisch. Kleine Hilfsfunktionen wie diese erhöhen die Komplexität zusätzlich. Im Allgemeinen zieht die Go-Philosophie es vor, die 3 einfachen Linien einer kniffligen Linie vorzuziehen.


Wie @robyoder erwähnt, json.Indent ist der Weg zu gehen. Ich dachte, ich würde diese kleine prettyprint -Funktion hinzufügen:

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 oder http://play.golang.org/p/R4LWpkkHIN

13
jpillora

Ich war frustriert darüber, dass es keine schnelle und qualitativ hochwertige Möglichkeit gab, JSON für eine kolorierte Zeichenfolge in Go zu verwenden, und schrieb daher meinen eigenen Marshaller mit dem Namen ColorJSON .

Damit können Sie mit sehr wenig Code auf einfache Weise eine Ausgabe wie diese erstellen:

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

Ich schreibe jetzt die Dokumentation dafür, war aber aufgeregt, meine Lösung zu teilen.

11
Tyler Brock

Hier ist was ich benutze. Wenn der JSON-Code nicht richtig gedruckt werden kann, wird nur die ursprüngliche Zeichenfolge zurückgegeben. Nützlich zum Drucken von HTTP-Antworten, die sollte JSON enthalten.

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()
}
6
Timmmm

Hier ist meine Lösung :

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

Ein einfacher, handelsüblicher Drucker in Go. Man kann es zu einer Binärdatei kompilieren durch:

go build -o jsonformat jsonformat.go

Es liest von der Standardeingabe, schreibt in die Standardausgabe und ermöglicht das Festlegen von Einrückungen:

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

Es erlaubt das Ausführen von bash Befehlen wie:

cat myfile | jsonformat | grep "key"
2
Paweł Szczur

ich bin ein bisschen neu zu gehen, aber das ist, was ich bisher gesammelt habe:

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
}

Dies ist die Ausführung der Funktion und nur 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)

}
1
accnameowl