Go를 사용하여 JSON을 예쁘게 인쇄하려면 어떻게해야합니까?


191

누구나 Go에서 JSON 출력을 예쁘게 인쇄하는 간단한 방법을 알고 있습니까?

주식 http://golang.org/pkg/encoding/json/ 패키지에는 이것에 대한 기능이 포함되어 있지 않은 것 같으며 (편집 : 허용, 답변 있음) 빠른 Google은 명백한 것을 나타내지 않습니다.

내가 찾고있는 용도는 결과를 예쁘게 인쇄하고 json.Marshal어디서나 JSON으로 가득 찬 문자열을 형식화하는 것이므로 디버그 목적으로 쉽게 읽을 수 있습니다.


경고 : 내 실험에서 JSON 사전에서 문자열 인덱스 괄호 묶어야 합니다 . 따라서 대부분의 Javascript 인터프리터가이를 사용하더라도{name: "value"} 괜찮지 않습니다 . Go JSON 라이브러리 함수 에서만 작동합니다. {"name": "value"}
peterh - 분석 재개 모니카

2
@ peterh JavaScript 리터럴 구문을 JSON과 혼동한다고 생각합니다. JSON 사양 ( json.org )은 문자열 리터럴 만 허용되며 (따옴표가 필요함을 나타냄) JS 언어 객체 구문에는 이러한 제한이 없습니다. Go 라이브러리는 사양을 따릅니다.
브래드 피바디

답변:


296

예쁜 글씨로, 나는 당신이 그렇게 들여 쓰기를 의미한다고 가정합니다.

{
    "data": 1234
}

오히려

{"data":1234}

이 작업을 수행하는 가장 쉬운 방법 MarshalIndent은을 사용하여 indent인수 를 통해 들여 쓰기를 원하는 방식을 지정할 수 있습니다 . 따라서 json.MarshalIndent(data, "", " ")들여 쓰기를 위해 4 개의 공백을 사용하여 예쁘게 인쇄합니다.


17
예, 그것은 단지 일처럼 보입니다-이미 내장되어 있으며 pkg 문서에 키워드 "pretty-print"를 포함하면 다음에 검색하는 사람이 찾을 수 있습니다. (문서 관리자에게 의견을 남길 것입니다.) Tks!
브래드 피바디

39
json.MarshalIndent(data, "", "\t")탭을 원한다면
Kyle Brandt

80
json.MarshalIndent(data, "", "🐱")고양이를 원한다면 죄송합니다
briiC 2016

45
json.MarshalIndent(data, "", "\t🐱")당신이 원한다면 ... 얼룩 고양이 ... 죄송합니다
Davos

78

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

48

더 나은 메모리 사용을 위해서는 이것이 더 낫습니다.

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

SetIndent최근에 추가 되었습니까 ? 그것은 본질적으로 가장 잘 알려져 있지 않습니다.
chappjc

1
@chappjc SetIndent(원래 이름이 Indent)는 2016 년 3 월에 추가되고 Go 1.7에서 릴리스되었습니다.이 질문은 원래 github.com/golang/go/commit/… github.com/golang/go/commit/에서
aoeu

19

Go에서 색상이 지정된 문자열에 JSON을 마샬링하는 빠르고 고품질의 방법이 없기 때문에 좌절했기 때문에 ColorJSON 이라는 내 마샬 러를 작성했습니다 .

그것으로 아주 작은 코드를 사용하여 다음과 같은 출력을 쉽게 생성 할 수 있습니다.

ColorJSON 샘플 출력

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

지금 문서를 작성하고 있지만 솔루션을 공유하게되어 기뻤습니다.


17

편집 되돌아 보면, 이것은 관용적이지 않은 바둑입니다. 이와 같은 작은 도우미 기능은 복잡한 단계를 추가합니다. 일반적으로 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


7

여기 내가 사용하는 것이 있습니다. JSON을 예쁘게 인쇄하지 못하면 원래 문자열을 반환합니다. 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()
}

6

내 해결책은 다음과 같습니다 .

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의 선반 형 예쁜 프린터. 다음을 통해 바이너리로 컴파일 할 수 있습니다.

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

어떻게 생겼는지


1

나는 갈 새로운 종류이지만, 이것은 내가 지금까지 모은 것입니다.

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)

}

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))
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.