2019年4月13日土曜日

golang で JSON を扱うサンプル

概要

標準パッケージである encoding/json を使います
map を json に変換したり json 文字列から map および struct を生成したりできます

環境

  • macOS 10.14.4
  • golang 1.11.5

map to json

json.Marshal() を使います

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    map1 := map[string]interface{}{
        "name": "hawksnowlog",
        "age":  20,
    }
    j1, err := json.Marshal(map1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(j1))
}

struct to json

map を json に変換しましたが struct でも同じようにできます

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Name string
    Age  int
}

func main() {
    st1 := MyStruct{
        Name: "hawksnowlog",
        Age:  20,
    }
    j1, err := json.Marshal(st1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(j1))
}

ただこの場合は struct のメンバ名に合わせて出力される json のキーも先頭が大文字になるので注意してください

json (string) to map

json.Unmarshal() を使います
第一引数にバイト配列を第二引数に変換先の変数のアドレスを指定します
第二引数で指定した型に変換できない場合は err になります

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    j1 := `{"name":"hawksnowlog","age":20}`
    var map1 map[string]interface{}
    err := json.Unmarshal([]byte(j1), &map1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(map1["name"].(string))
    fmt.Println(map1["age"].(float64))
    // fmt.Println(int(map1["age"].(float64))) to int
}

json (string) to struct

先程は map に Unmarshal しましたが今回は struct に変換します
おそらくこれが一番安全なやり方だと思います

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Name string
    Age  int
}

func main() {
    j1 := `{"name":"hawksnowlog","age":20}`
    var st1 MyStruct
    err := json.Unmarshal([]byte(j1), &st1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(st1.Name)
    fmt.Println(st1.Age)
}

対応しないメンバが存在する場合はそれぞれの型のデフォルト値が設定されます

バインドするフィールド名を指定する

デフォルトは struct のメンバ名に該当するフィールドを json から探してそれにバインドします
メンバ名とフィールド名が異なる場合は指定することも可能です

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Name string `json:"account_name"`
    Age  int
}

func main() {
    j1 := `{"account_name":"hawksnowlog","age":20}`
    var st1 MyStruct
    err := json.Unmarshal([]byte(j1), &st1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(st1.Name)
    fmt.Println(st1.Age)
}

デフォルト値を設定する

先程、該当するフィールド名がない場合は各型のデフォルト値が設定されると説明しました
設定されるデフォルト値を独自で設定したい場合は構造体を生成するときに指定することができます

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Name string `json:"account_name"`
    Age  int    `json:"account_age"`
}

func main() {
    j1 := `{"account_name":"hawksnowlog","age":20}`
    st1 := MyStruct{
        Age: 30,
    }
    err := json.Unmarshal([]byte(j1), &st1)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(st1.Name)
    fmt.Println(st1.Age)
}

上記の場合、json 内に「account_age」がないので Age=0 になるところですが構造体を生成するときに Age=30 で初期化しているため json.Unmarshal 後の値も 30 になっています

最後に

  • json.Marshal するときは map や構造体をそのまま入れる
  • json.Unmarshal するときは変換先の map や構造体と一緒にバイト配列の json を入れる

と覚えておけば大抵の場合は対応できると思います

0 件のコメント:

コメントを投稿