Go言語 – 15.JSONのパース/生成

2019-02-08Go言語

JSONのパース/生成

JSON形式を扱うには、encoding/jsonパッケージを使用します。

パース処理

JSON形式の文字列をパースするには、JSONのデータ構造に合わせて構造体を定義し、Unmarshal関数を使用します。

package main

import (
    "encoding/json"
    "fmt"
)

type Country struct {
    Name string              `json:"name"`
    Prefectures []Prefecture `json:"prefectures"`
}

type Prefecture struct {
    Name string    `json:"name"`
    Capital string `json:"capital"`
    Population int `json:"population"`
}

func main() {
    jsonStr := `
{
    "name": "日本",
    "prefectures": [
        {
            "name": "大阪府",
            "capital": "大阪市",
            "population": 2726905
        },
        {
            "name": "兵庫県",
            "capital": "神戸市",
            "population": 1525615
        },
        {
            "name": "京都府",
            "capital": "京都市",
            "population": 1470627
        }
    ]
}
`
    jsonBytes := ([]byte)(jsonStr)
    data := new(Country)

    if err := json.Unmarshal(jsonBytes, data); err != nil {
        fmt.Println("JSON Unmarshal error:", err)
        return
    }

    fmt.Println(data.Name)
    fmt.Println(data.Prefectures[0].Name)
    fmt.Println(data.Prefectures[1].Capital)
    fmt.Println(data.Prefectures[2].Population)
}

【結果】
日本
大阪府
神戸市
1470627

タグについて

構造体のメンバ変数宣言の後ろに'json:“xxx”’という形式の文字列が付けられていますが、これはタグと呼ばれるものです。
タグは変数の性質には全く影響しませんが、reflectパッケージを用いることで変数につけられたタグを取得することができます。

encoding/jsonパッケージでは、タグを利用してJSON内のキー名と各変数の結びつけを行っています。タグを省略した場合は変数名と全く同じ名前のキーが自動的に結び付けられます。

生成処理

構造体のJSON文字列表現を生成するには、Marshal関数を使用します。

package main

import (
    "encoding/json"
    "fmt"
)

type Country struct {
    Name string              `json:"name"`
    Prefectures []Prefecture `json:"prefectures"`
}

type Prefecture struct {
    Name string    `json:"name"`
    Capital string `json:"capital"`
    Population int `json:"population"`
}

func main() {
    osaka := Prefecture{Name:"大阪府", Capital:"大阪市", Population:2726905}
    kobe := Prefecture{Name:"兵庫県", Capital:"神戸市", Population:1525615}
    kyoto := Prefecture{Name:"京都府", Capital:"京都市", Population:1470627}
    japan := Country{
        Name:"日本",
        Prefectures:[]Prefecture{osaka, kobe, kyoto},
    }

    jsonBytes, err := json.Marshal(japan)
    if err != nil {
        fmt.Println("JSON Marshal error:", err)
        return
    }

    fmt.Println(string(jsonBytes))
}


JSON文字列としては書式通りですが、可読性のために改行やインデントを加えたい、というケースがあります。その場合は<strong>Indent</strong>関数を使用し、インデント済みの文字列を<strong>bytes.Buffer</strong>に書き込みます。

package main

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

type Country struct {
    Name string              `json:"name"`
    Prefectures []Prefecture `json:"prefectures"`
}

type Prefecture struct {
    Name string    `json:"name"`
    Capital string `json:"capital"`
    Population int `json:"population"`
}

func main() {
    osaka := Prefecture{Name:"大阪府", Capital:"大阪市", Population:2726905}
    kobe := Prefecture{Name:"兵庫県", Capital:"神戸市", Population:1525615}
    kyoto := Prefecture{Name:"京都府", Capital:"京都市", Population:1470627}
    japan := Country{
        Name:"日本",
        Prefectures:[]Prefecture{osaka, kobe, kyoto},
    }

    jsonBytes, err := json.Marshal(japan)
    if err != nil {
        fmt.Println("JSON Marshal error:", err)
        return
    }

    out := new(bytes.Buffer)
    // プリフィックスなし、スペース4つでインデント
    json.Indent(out, jsonBytes, "", " ")
    fmt.Println(out.String())
}
【結果】
{
    "name": "日本",
    "prefectures": [
        {
            "name": "大阪府",
            "capital": "大阪市",
            "population": 2726905
        },
        {
            "name": "兵庫県",
            "capital": "神戸市",
            "population": 1525615
        },
        {
            "name": "京都府",
            "capital": "京都市",
            "population": 1470627
        }
    ]
}