MyDocs

# Golangでjsonを操作する

JSON の解析

今回使う JSON ファイル。

{
  "id": 1,
  "content": "Hello",
  "author": {
    "id": 1,
    "name": "author1"
  },
  "comments": [
    {
      "id": 1,
      "content": "comment1",
      "author": "author2"
    },
    {
      "id": 2,
      "content": "comment2",
      "author": "author3"
    }
  ]
}

Unmarshal を使う

文字列データの場合は Unmarshal を使う。

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

type Post struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  struct {
		Id   int    `json:"id"`
		Name string `json:"name"`
	} `json:"author"`
	Comments []struct {
		Id      int    `json:"id"`
		Content string `json:"content"`
		Author  string `json:"author"`
	} `json:"comments"`
}

func main() {
	jsonFile, err := os.Open("file.json")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer jsonFile.Close()

	jsonData, err := ioutil.ReadAll(jsonFile)
	if err != nil {
		fmt.Println(err)
		return
	}

	var post Post
	json.Unmarshal(jsonData, &post)
	fmt.Println(post) // {1 Hello {0 author1} [{1 comment1 author2} {2 comment2 author3}]}
}

デコーダを使う

http.Request の Body のように io.Reader のストリームからデータが入ってくる場合に使う。

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
)

type Post struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  struct {
		Id   int    `json:"id"`
		Name string `json:"name"`
	} `json:"author"`
	Comments []struct {
		Id      int    `json:"id"`
		Content string `json:"content"`
		Author  string `json:"author"`
	} `json:"comments"`
}

func main() {
	jsonFile, err := os.Open("file.json")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer jsonFile.Close()

	decoder := json.NewDecoder(jsonFile)
	for {
		var post Post
		err := decoder.Decode(&post)
		if err == io.EOF {
			break
		}
		if err != nil {
			fmt.Println(err)
			return
		}
		fmt.Println(post) // {1 Hello {1 author1} [{1 comment1 author2} {2 comment2 author3}]}
	}
}

JSON データを作成する

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
)

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}
type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}
type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

func main() {
	post := Post{
		Id:      1,
		Content: "Hello",
		Author: Author{
			Id:   1,
			Name: "author1",
		},
		Comments: []Comment{
			{
				Id:      1,
				Content: "comment1",
				Author:  "author2",
			},
			{
				Id:      2,
				Content: "comment2",
				Author:  "author3",
			},
		},
	}
	output, err := json.MarshalIndent(&post, "", "\t\t")
	if err != nil {
		fmt.Println(err)
		return
	}
	err = ioutil.WriteFile("created.json", output, 0644)
	if err != nil {
		fmt.Println(err)
		return
	}
}

エンコーダを使う

package main

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

type Post struct {
	Id       int       `json:"id"`
	Content  string    `json:"content"`
	Author   Author    `json:"author"`
	Comments []Comment `json:"comments"`
}
type Author struct {
	Id   int    `json:"id"`
	Name string `json:"name"`
}
type Comment struct {
	Id      int    `json:"id"`
	Content string `json:"content"`
	Author  string `json:"author"`
}

func main() {
	post := Post{
		Id:      1,
		Content: "Hello",
		Author: Author{
			Id:   1,
			Name: "author1",
		},
		Comments: []Comment{
			{
				Id:      1,
				Content: "comment1",
				Author:  "author2",
			},
			{
				Id:      2,
				Content: "comment2",
				Author:  "author3",
			},
		},
	}
	jsonFile, err := os.Create("created.json")
	if err != nil {
		fmt.Println(err)
		return
	}
	encoder := json.NewEncoder(jsonFile)
	err = encoder.Encode(&post)
	if err != nil {
		fmt.Println(err)
		return
	}
}