Go kullanarak JSON'u nasıl güzel yazdırabilirim?


191

Go'da JSON çıktısını yazdırmanın basit bir yolunu bilen var mı?

Hisse senedi http://golang.org/pkg/encoding/json/ paketi bunun için işlevsellik içermiyor gibi görünüyor (EDIT: öyle, kabul edilen cevaba bakın) ve hızlı bir google bariz bir şey ortaya çıkarmıyor.

Aradığım kullanımlar hem sonucu çok güzel yazdırıyor hem de json.MarshalJSON ile dolu bir dizeyi her yerden biçimlendiriyor, bu nedenle hata ayıklama amacıyla okumak daha kolay.


Uyarı: Deneylerimde, JSON sözlüklerinde dizeler dizinleri parantez içine alınmalıdır . Bu yüzden, çoğu Javascript tercümanı kullanmasına rağmen{name: "value"} iyi olmayacak . Yalnızca Go JSON kitaplığı işlevleriyle çalışır. {"name": "value"}
peterh - Monica

2
@peterh Bence JavaScript değişmez sözdizimini JSON ile karıştırıyorsunuz. JSON spec ( json.org ), açıkça yalnızca dize değişmezlerine izin verildiğini (tırnak içine alınması gerektiği anlamına gelir) belirtirken, JS dil nesnesi sözdiziminde bu kısıtlama yoktur. Go kitaplığı teknik özellikleri takip ediyor.
Brad Peabody

Yanıtlar:


296

Güzel baskı ile, sanırım girintili demek istedim

{
    "data": 1234
}

ziyade

{"data":1234}

Bunu yapmanın en kolay yolu MarshalIndent, indentargüman aracılığıyla nasıl girintili olmasını istediğinizi belirtmenize izin verir . Böylece, json.MarshalIndent(data, "", " ")girinti için dört boşluk kullanarak güzel yazdırır.


17
Evet, bu sadece bir şey gibi görünüyor - zaten yerleşik, sadece sol pkg doc "pretty-print" anahtar kelimesini dahil etmektir, böylece arama yapan bir sonraki adam onu ​​bulur. (Doktor koruyucular için bir geri bildirim notu bırakacaktır.) Tks!
Brad Peabody

39
json.MarshalIndent(data, "", "\t")sekmeler istiyorsanız.
Kyle Brandt

81
json.MarshalIndent(data, "", "🐱")kediler istiyorsan. üzgünüm
briiC

45
json.MarshalIndent(data, "", "\t🐱")isterseniz ... tekir kedi ... üzgünüm
Davos

78

JSON'a dönüştürmek istediğiniz bir nesneniz varsa, kabul edilen cevap harikadır. Soru da sadece herhangi bir JSON dizesini güzel baskıdan bahsediyor ve ben de bunu yapmaya çalışıyordum. Ben sadece bazı JSON bir POST isteği (özellikle bir CSP ihlali raporu ) günlüğe kaydetmek istedim .

Kullanmak için MarshalIndentbunu Unmarshalbir nesneye dönüştürmeniz gerekir . Buna ihtiyacın varsa, git, ama ben yapmadım. Sadece bir bayt dizisini güzel yazdırmanız gerekiyorsa, düz Indentsizin arkadaşınızdır.

İşte sonuçta:

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

48

Daha iyi bellek kullanımı için sanırım bu daha iyi:

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

Did SetIndentolsun yeni eklenen? Çoğu kişi tarafından bilinmemektedir.
chappjc

1
@chappjc SetIndent(başlangıçta adlandırılmış Indent) Mart 2016'da eklendi ve bu sorunun ilk sorulmasından yaklaşık 3 yıl sonra Go 1.7'de yayınlandı: github.com/golang/go/commit/… github.com/golang/go/commit/ …
aoeu

19

Go'da renklendirilmiş bir dizeye JSON marshal JSON için hızlı, yüksek kaliteli bir yol olmaması nedeniyle hayal kırıklığına uğradım, bu yüzden ColorJSON adlı kendi Mareşallerimi yazdım .

Bununla birlikte, çok az kod kullanarak kolayca böyle bir çıktı üretebilirsiniz:

ColorJSON örnek çıktısı

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

Bunun için belgeleri şimdi yazıyorum, ancak çözümümü paylaşmaktan heyecan duydum.


17

Düzenle Geriye baktığımızda, bu deyimsel olmayan Go. Bunun gibi küçük yardımcı işlevler ekstra bir karmaşıklık adımı ekler. Genel olarak, Go felsefesi 3 zor çizgiyi 1 zor çizgiye eklemeyi tercih eder.


@Robyoder'in de belirttiği gibi, gitmenin json.Indentyolu budur. Bu küçük prettyprintişlevi ekleyeceğimi düşündüm :

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


7

İşte kullandığım. JSON'u güzel bir şekilde yazdıramıyorsa, yalnızca orijinal dizeyi döndürür. JSON içermesi gereken HTTP yanıtlarını yazdırmak için kullanışlıdır.

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

İşte benim çözümüm :

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
}

2

Go raf güzel bir yazıcı kapalı bir basit. Bir ikiliye şu şekilde derlenebilir:

go build -o jsonformat jsonformat.go

Standart girişten okur, standart çıkışa yazar ve girintiyi ayarlamaya izin verir:

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

Aşağıdaki gibi bir bash komutunu çalıştırmaya izin verir:

cat myfile | jsonformat | grep "key"

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

Nasıl görünüyor


1

Ben gitmek için yeni bir tür, ama şimdiye kadar toplanan budur:

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
}

Bu fonksiyonun yürütülmesi ve sadece standart

b, _ := json.MarshalIndent(SomeType, "", "\t")

Kod:

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)

}

0
//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))
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.