Goで簡単にJSON形式を扱うパッケージ： go-simplejson

Goで__JSON__ 形式を扱おうとすると、組み込みの`encoding/json`パッケージでは構造体を使わないとデータにアクセスできないため、pythonライクに簡単なものとして扱いたい自分にとっては多々つらいところがありました。
そこでいろいろ検索してみたところ、同じように考えた人がやはりいるようで以下の二つのパッケージにたどり着くことができました。

+ [go-scan][go-scan]
+ [go-simplejson][go-simplejson]

__go-scan__ は __mattn__ さんが作られたパッケージで、 __JSON__ 形式の読み込みや値の取得を簡単・便利にしてくれます。
一方、 __go-simplejson__ は __bitly__ 社が[MITライセンス][go-simplejson.license]で公開されているもので、 __go-scan__ に比べると少し手間はかかりますが、 __JSON__ 形式の読み込みや値の取得が簡単に行える他、さらにkeyの追加や削除、変更したデータの`[]byte`型への変換も可能にしてくれるパッケージです。
この __go-simplejson__ は日本語の記事をほとんど見かけませんでしたが、 __JSON__ に変更を加えることが出来る機能は個人的に有用だと考えたため、その覚書として本記事を残すことにしました。
本記事の内容は[godoc][go-simplejson.godoc]を参考に書いており、また自分もGoを触り始めてまだ日も浅いので、挙動を正確に記述していない可能性があります。ご了承ください。

[go-scan]: https://github.com/mattn/go-scan
[go-simplejson]: https://github.com/bitly/go-simplejson
[go-simplejson.license]: https://github.com/bitly/go-simplejson/blob/master/LICENSE
[go-simplejson.godoc]: http://godoc.org/github.com/bitly/go-simplejson

##パッケージ取得
パッケージは`go get`で取得可能です。

```bash
go get github.com/bitly/go-simplejson
```


##使い方

下記のような内容の`sample.json`ファイルを対象としたコードです。

```json
{
    "hoge": true,
    "piyo":{
        "foo":[1,2],
        "bar":"test"
    }
}
```


```go

package main

import (
    "fmt"
    "github.com/bitly/go-simplejson"
    "io/ioutil"
    "log"
    "os"
)

func main() {
    // ファイルの読み込み
    rf, err := ioutil.ReadFile("./sample.json") //[]byte型での読み込み
    // r, err := os.Open("./sample.json") //File型での読み込み
    if err != nil {
        log.Fatal(err)
    }

    // []byte型からjson型への変換
    js, err := simplejson.NewJson(rf)
    // []byte型であれば New() を使ってjson型を先んじて作成し、
    // UnmarshalJSON() を使って変換することも可能です。
    // js := simplejson.New()
    // js.UnmarshalJSON(rf)
    // File型で読み込んだ場合は下記のように変換できます。
    // js, err := simplejson.NewFromReader(r)

    // 値の取得
    // 各値は　Get()　や GetPath() とその値の型名と同じ名前の関数を使って取得できます。
    // Get() では一つずつkeyを記述するのに対し、 GetPath() では一括して記述することが出来ます。
    // また、 Typename() では値とエラーを返し、 MustTypename() では値のみを返します。
    b, err := js.Get("hoge").Bool()
    m, _ := js.Get("piyo").Map()
    a := js.Get("piyo").Get("foo").MustArray()
    s := js.GetPath("piyo", "bar").MustString()
    fmt.Println(b, m, a, s)

    // 値の変更
    // Set() や SetPath() を使うことが出来ます。
    // SetPath() については下記のkeyの追加、削除の項を参考にしてください。
    js.Get("piyo").Set("bar", "test2")
    fmt.Println(js.GetPath("piyo", "bar").String())

    // keyの追加
    // Set() や SetPath() を使うことでkeyの追加も行えます。
    // SetPath() では GetPath() と違い、引数に []string{} をとります。
    // Set() では直下のkeyしか追加できませんが、SetPath() ではさらに下のkeyも追加できます。
    js.Get("piyo").Set("new_hoge", true)
    js.SetPath([]string{"piyo", "new_piyo", "new_foo"}, []int{3, 4})
    fmt.Println(js.GetPath("piyo", "new_hoge").Bool())
    // 本来はArray()で取得したいところなのですが、何故か取得できないためInterface()で無理やり取得しています。
    fmt.Println(js.GetPath("piyo", "new_piyo", "new_foo").Interface())

    // keyの削除
    // Del() を使うことでkeyそのものを削除できます。
    js.Get("piyo").Del("new_hoge")
    fmt.Println(js.GetPath("piyo", "new_hoge").Bool()) //値の取得に失敗する

    // json型から[]byte型への変換
    // json型を[]byte型に変換する関数は3つ用意されています。
    // MarshalJSON() や Encode() では単純な変換を行い、
    // EncodePretty() ではインデントされた状態に変換することが出来ます。
    w, err := os.Create("./result.json")
    defer w.Close()
    // o, _ := js.MarshalJSON()
    // o, _ := js.Encode()
    o, _ := js.EncodePretty()
    w.Write(o)
}

```

##値取得用関数

|Typename|説明|
|:---|:---|
| __Array()__ |配列|
| __Bool()__ |論理値|
| __Bytes()__ |[]byte|
| __Float64()__ |64bit浮動小数点|
| __Int()__ |符号付整数|
| __Int64()__ |64bit符号付整数|
| __Interface()__ |interface{}|
| __Map()__ |map|
| __String()__ |文字列|
| __StringArray()__ |文字列配列|
| __Uint64()__ |64bit符号なし整数|

これらの関数はすべてその値とエラーの二値を返します。また __Bytes()__ 、 __Interface()__ 、 __StringArray()__ 以外は __MustTypename()__ 関数が存在します。

さらに詳しい内容に関しては[GoDoc][go-simplejson.godoc]を参照してください。

##備考
個人的に __GetPath()__ 関数の引数のとり方が若干使いにくかったので、下記のように`simplejson.go`ファイルに、文字列の配列を引数として受け取る __GetPathWithArray()__ を追加しています。
引数のとり方以外は __GetPath()__ 関数と全く同じです。

```go

func (j *Json) GetPathWithArray(branch []string) *Json {
    jin := j
    for _, p := range branch {
        jin = jin.Get(p)
    }
    return jin
}
```