Go
JSON

GoでJSONを雑に書く

テストのフィクスチャなどで、JSONを雑に書きたくなることがあるのだけど、
文字列で定義するとJSONとしての構文チェックができず不便だ。trailing commaとか、クオートの不備とかを気にして書かなくてはいけない。

js := `{
  "baa": {
    "a": 1,
    "b": 1.9,
    "c": "abc"
  },
  "foo": {
    "baa": "muu",
    "bababa": "gagaga"
  }
}`

なので、Goとして構造を定義して、json.Marshal()したくなる。

https://golang.org/pkg/encoding/json/

json.Marshalは構造体を渡すことも多いが、雑に map[string]interface{} を渡しても動作する。これを使って書いていくとよい。

tips

  • map[string]interface{}だと長いので、適当に型を定義して使うと便利。
  • json.Marshalはエラーが発生する可能性があるが、自分でコード中で定義したjson構造がバグってたらどうしようもないので、エラーをpanic化してしまう雑な関数を定義してしまうのも便利。
  • json.Indentでインデントするのもいいぞ
  • []bytesで扱うか string で扱うかは状況によるので適宜切り替えてください。
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
)

type object map[string]interface{}
type oo map[string]object

func MustJsonString(obj interface{}) string {
    b, err := json.Marshal(obj)
    if err != nil {
        panic(err)
    }
    var out bytes.Buffer
    err = json.Indent(&out, b, "", "  ")
    if err != nil {
        panic(err)
    }
    return out.String()
}

func main() {
    js := oo{
        "foo": {
            "baa":    "muu",
            "bababa": "gagaga",
        },
        "baa": {
            "a": 1,
            "b": 1.9,
            "c": "abc",
        },
    }
    fmt.Println(MustJsonString(js))
}