JSON #
値を JSON にエンコードする #
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string
Age int
}
func main() {
// 構造体から JSON
u := User{Name: "User1", Age: 20}
data, err := json.Marshal(u)
fmt.Println(string(data), err) // == {"Name":"User1","Age":20} <nil>
// スライスから JSON
s := []string{"foo", "bar", "buz"}
data, err = json.Marshal(s)
fmt.Println(string(data), err) // == ["foo","bar","buz"] <nil>
// マップから JSON
m := map[string]string{
"key1": "val1",
"key2": "val2",
"key3": "val3",
}
data, err = json.Marshal(m)
fmt.Println(string(data), err) // == {"key1":"val1","key2":"val2","key3":"val3"} <nil>
}
参考ドキュメント: encoding/json
JSON から値へデコードする #
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string
Age int
}
func main() {
// JSON から構造体
data := []byte(`{"Name":"User1","Age":20}`)
u := new(User)
if err := json.Unmarshal(data, u); err != nil {
panic(err)
}
fmt.Printf("%#v \n", u) // == &main.User{Name:"User1", Age:20}
// JSON からスライス
data = []byte(`["foo","bar","buz"]`)
s := []string{}
if err := json.Unmarshal(data, &s); err != nil {
panic(err)
}
fmt.Printf("%#v \n", s) // == []string{"foo", "bar", "buz"}
// JSON からマップ
data = []byte(`{"key1":"val1","key2":"val2","key3":"val3"}`)
m := map[string]string{}
if err := json.Unmarshal(data, &m); err != nil {
panic(err)
}
fmt.Printf("%#v \n", m) // == map[string]string{"key1":"val1", "key2":"val2", "key3":"val3"}
}
参考ドキュメント: encoding/json
JSON エンコードまたはデコードする際にフィールド名を指定する #
構造体のフィールド定義のタグで JSON にエンコードした際あるいはデコードする際のフィールド名を指定できる。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
// JSON エンコード
u1 := User{Name: "user1", Age: 10}
data1, err := json.Marshal(u1)
if err != nil {
panic(err)
}
fmt.Println(string(data1)) // == {"name":"user1","age":10}
// JSON デコード
data2 := []byte(`{"name":"user2","age":20}`)
u2 := new(User)
if err := json.Unmarshal(data2, u2); err != nil {
panic(err)
}
fmt.Printf("%#v \n", u2) // == &main.User{Name:"user2", Age:20}
}
参考ドキュメント: encoding/json
JSON エンコード処理をカスタマイズする #
JSON のエンコードをする json.Marshal
はエンコード対象が func MarshalJSON() ([]byte, error)
を実装している場合に
デフォルトのエンコード処理の代わりに MarshalJSON
を実行する。
MarshalJSON
はメソッドのレシーバからエンコード対象の情報を取得し、JSON に加工して []byte として返すメソッド。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string
Age int
Gender int
}
func (u User) MarshalJSON() ([]byte, error) {
m := map[string]interface{}{}
m["name"] = u.Name
m["years"] = u.Age
switch u.Gender {
case 1:
m["gender"] = "male"
case 2:
m["gender"] = "female"
default:
m["gender"] = "other"
}
if u.Age < 20 {
m["is_child"] = true
}
return json.Marshal(m)
}
func main() {
u := User{Name: "user1", Age: 10, Gender: 2}
data, err := json.Marshal(u)
if err != nil {
panic(err)
}
fmt.Println(string(data)) // == {"gender":"female","is_child":true,"name":"user1","years":10}
}
参考ドキュメント: encoding/json
JSON デコード処理をカスタマイズする #
JSON のデコードをする json.Unmarshal
はデコード先が func UnmarshalJSON(b []byte) error
を実装している場合に
デフォルトのデコード処理の代わりに UnmarshalJSON
を実行する。
UnmarshalJSON
は引数 b として JSON を受け取り、レシーバの値にデコードしたデータを入れていくメソッド。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string
Age int
Gender int
}
func (u *User) UnmarshalJSON(b []byte) error {
m := map[string]interface{}{}
if err := json.Unmarshal(b, &m); err != nil {
return err
}
if v, ok := m["name"]; ok {
if s, ok := v.(string); ok {
u.Name = s
}
}
if v, ok := m["years"]; ok {
if i, ok := v.(float64); ok {
u.Age = int(i)
}
}
if v, ok := m["gender"]; ok {
if s, ok := v.(string); ok {
switch s {
case "male":
u.Gender = 1
case "female":
u.Gender = 2
default:
u.Gender = 0
}
}
}
return nil
}
func main() {
data := []byte(`{"gender":"female","is_child":true,"name":"user1","years":10}`)
u := new(User)
err := json.Unmarshal(data, u)
if err != nil {
panic(err)
}
fmt.Printf("%#v", u) // == &main.User{Name:"user1", Age:10, Gender:2}
}
参考ドキュメント: encoding/json