json.Unmarshal
このページでは豊富な例を用いてGolangのjsonパッケージのUnmarshal関数の使い方を学ぶことができます。
Unmarshal関数はjsonパッケージの関数の1つです。
第1引数で与えたJSONデータを第2引数で指定した値にマッピングします。
返り値としてerror型の値を返し、エラーが発生しない場合はnil
となります。
// 記述例
import "encoding/json"
エラー := json.Unmarshal(JSONデータ, マッピングされる値)
TL;DR
基本
// 第1引数にJSONデータ、第2引数にJSONデータをマッピングする値を指定する
// JSONデータの生成
jsonData1 := []byte(`{
"ID": 1,
"Name": "Alex"
}`)
type Person struct {
ID int
Name string
}
// JSONデータのマッピング(第2引数にポインタを渡す)
var person1 Person
err := json.Unmarshal(jsonData1, &person1)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", person1)
==> {ID:1 Name:Alex}
// JSONデータのキーの大文字・小文字に関係なくマッピングされる
jsonData2 := []byte(`{
"id": 1,
"namE": "Alex"
}`)
var person2 Person
if err := json.Unmarshal(jsonData2, &person2); err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", person2)
==> {ID:1 Name:Alex}
// Unmarshalの第2引数にポインタが渡されないとエラー
jsonData3 := []byte(`{
"ID": 1,
"Name": "Alex"
}`)
var person3 Person
if err := json.Unmarshal(jsonData3, person3); err != nil {
fmt.Println(err)
}
==> (エラー)json: Unmarshal(non-pointer (パッケージ名).Person)
fmt.Printf("%+v\n", person3)
==> {ID:0 Name:}
// 配列型のJSONの場合
jsonData4 := []byte(`["go", "golang"]`)
var array4 []string
if err := json.Unmarshal(jsonData4, &array4); err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", array4)
==> [go golang]
// マップ(map)にマッピングする場合
jsonData5 := []byte(`{"go": 0, "golang": 1}`)
var map5 map[string]int
_ = json.Unmarshal(jsonData5, &map5)
fmt.Printf("%+v\n", map5)
==> map[go:0 golang:1]
// interface{}型の変数にマッピングする場合
jsonData6 := []byte(`{
"ID": 1,
"Name": "Alex",
"Friends": ["Olivia", "Xiaoran"]
}`)
var interface6 interface{}
_ = json.Unmarshal(jsonData6, &interface6)
fmt.Printf("%+v\n", interface6)
==> map[Friends:[Olivia Xiaoran] ID:1 Name:Alex]
// 型はキーがstring、値がinterface{}のマップとなる
fmt.Printf("%T\n", interface6)
==> map[string]interface {}
関連情報:array型(配列)の解説
関連情報:map型(マップ)の解説
フィールド名とフィールドタグによるマッピング挙動
// 同一パッケージ外からアクセスできない構造体のフィールド(Non-exported field、最初が大文字ではないフィールド)はマッピングされない
type Language struct {
ID int
name string
}
jsonData1 := []byte(`{
"ID": 1,
"name": "Hindi"
}`)
var language1 Language
_ = json.Unmarshal(jsonData1, &language1)
fmt.Printf("%+v\n", language1)
==> {ID:1 name:}
// フィールドタグで指定されている名前がマッピングされる
type Language2 struct {
ID int `json:"lang_id"`
Name string `json:"lang_name"`
}
// JSONのキー名がフィールドタグと異なるとマッピングされない
jsonData2 := []byte(`{
"ID": 2,
"Name": "Chinese"
}`)
var language2 Language2
_ = json.Unmarshal(jsonData2, &language2)
fmt.Printf("%+v\n", language2)
==> {ID:0 Name:}
// JSONのキー名がフィールドタグと一致する場合
jsonData3 := []byte(`{
"lang_id": 2,
"lang_name": "Chinese"
}`)
var language3 Language2
_ = json.Unmarshal(jsonData3, &language3)
fmt.Printf("%+v\n", language3)
==> {ID:2 Name:Chinese}
マッピングされなかったフィールドの扱い
type Person struct {
Name string
Age int
IsStudent bool
Friends []string
}
// JSONのキーにマッピング対象のフィールドが存在しない場合はゼロ値(zero value)が割り当てられる
jsonData1 := []byte(`{
"FooBarNinja": true
}`)
var person1 Person
_ = json.Unmarshal(jsonData1, &person1)
fmt.Printf("%+v\n", person1)
==> {Name: Age:0 IsStudent:false Friends:[]}
// JSONに存在しないフィールドをnilにしたい場合
type Person2 struct {
Name *string
Age *int
IsStudent *bool
Friends *[]string
}
jsonData2 := []byte(`{
"FooBarNinja": true
}`)
var person2 Person2
_ = json.Unmarshal(jsonData2, &person2)
fmt.Printf("%+v\n", person2)
==> {Name:<nil> Age:<nil> IsStudent:<nil> Friends:<nil>}
JSONへの変換
type Guest struct {
ID int
Name string
}
// JSONから構造体へのマッピング
jsonData1 := []byte(`{
"id": 1,
"name": "Johnson"
}`)
var guest1 Guest
_ = json.Unmarshal(jsonData1, &guest1)
fmt.Printf("%+v\n", guest1)
==> {ID:1 Name:Johnson}
// 構造体からJSONへの変換
encodedJson, err := json.Marshal(guest1)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", encodedJson)
==> {"ID":1,"Name":"Johnson"}
関連情報:json.Marshalの使用方法
解説
// 記述例
import "encoding/json"
エラー := json.Unmarshal(JSONデータ, マッピングされる値)
基本
Unmarshal関数はJSONデータを値にマッピングすることができます。
第1引数に「マッピングしたいJSONデータ([]byte型)」を、第2引数に「マッピングされる値(interface{}型)のポインタ」を指定します。
第2引数にポインタを指定しない場合、エラーが発生してJSONデータがマッピングされません。
返り値はerror型の値が返り、エラーが発生しない場合は返り値はnil
となります。
マッピングされるJSONデータのキーは、マッピングされるフィールドの大文字・小文字が完全に一致しなくともマッピングされます。
// マッピング元のJSONデータ
jsonData1 := []byte(`{
"Name": "Kiwi",
"Price": 100
}`)
type Fruit struct {
Name string
Price int
}
var fruit1 Fruit
err := json.Unmarshal(jsonData1, &fruit1)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", fruit1)
==> {Name:Kiwi Price:100}
// JSONデータのキーの大文字・小文字に関係なくマッピングされる
jsonData2 := []byte(`{
"name": "Kiwi",
"price": 100
}`)
var fruit2 Fruit
if err := json.Unmarshal(jsonData2, &fruit2); err != nil {
fmt.Println(err)
}
fmt.Printf("%+v\n", fruit2)
==> {Name:Kiwi Price:100}
// 第2引数にポインタが渡されないとエラー
jsonData3 := []byte(`{
"name": "Apple",
"price": 200
}`)
var fruit3 Fruit
if err := json.Unmarshal(jsonData3, fruit3); err != nil {
fmt.Println(err)
}
==> (エラー)json: Unmarshal(non-pointer (パッケージ名).Fruit)
fmt.Printf("%+v\n", fruit3)
==> {Name: Price:0}
// 配列型のJSONからのマッピング
jsonData4 := []byte(`[true, true, false]`)
var array4 []bool
_ = json.Unmarshal(jsonData4, &array4)
fmt.Printf("%+v\n", array4)
==> [true true false]
// マップ(map)へのマッピング
jsonData5 := []byte(`{"go": "Go", "golang": "Golang"}`)
var map5 map[string]string
_ = json.Unmarshal(jsonData5, &map5)
fmt.Printf("%+v\n", map5)
==> map[go:Go golang:Golang]
// interface{}型へのマッピング
jsonData6 := []byte(`{
"Name": "Banana",
"Price": 300,
"Discount": {
"Type": "weekend"
}
}`)
var interface6 interface{}
_ = json.Unmarshal(jsonData6, &interface6)
fmt.Printf("%+v\n", interface6)
==> map[Discount:map[Type:weekend] Name:Banana Price:300]
// 型はキーがstring、値がinterface{}のマップ
fmt.Printf("%T\n", interface6)
==> map[string]interface {}
関連情報:array型(配列)の解説
関連情報:map型(マップ)の解説
フィールド名とフィールドタグによるマッピング挙動
構造体(struct)の「小文字から始まる名前を持つフィールド(Non-exported field)」は外部パッケージからアクセスすることができません。
このようなフィールドはUnmarshal関数を使用してマッピングした場合もJSONデータはマッピングされず、ゼロ値が設定されます。
また、構造体のフィールドタグにjson
というキーが指定されている場合、
JSONデータから第2引数にマッピングされるものは「フィールドタグで指定した名前」と一致するものだけです。
// 同一パッケージ外からアクセスできない構造体フィールド(Non-exported field、最初が大文字ではないフィールド)にマッピングする場合
type Student struct {
Name string
score int
}
jsonData1 := []byte(`{
"Name": "Anika",
"score": 100
}`)
var student1 Student
_ = json.Unmarshal(jsonData1, &student1)
// scoreのJSONデータはマッピングされず、intのゼロ値である0が割り当てられる
fmt.Printf("%+v\n", student1)
==> {Name:Anika score:0}
// フィールドタグでjsonのキー名が指定されている場合
type Student2 struct {
Name string `json:"student_name"`
Score int `json:"student_score"`
}
// jsonのキー名とフィールドタグが一致する値のみマッピングされる
jsonData2 := []byte(`{
"Name": "Anika",
"student_score": 100
}`)
var student2 Student2
_ = json.Unmarshal(jsonData2, &student2)
fmt.Printf("%+v\n", student2)
==> {Name: Score:100}
マッピングされなかったフィールドの扱い
JSONデータ内にフィールドに値するデータが存在せず、第2引数にマッピングされなかった第2引数のフィールドは、
ゼロ値(zero value)と呼ばれる値に設定されます。
ゼロ値がどのような値であるかはフィールドに指定した型によって異なります。
マッピングされなかったフィールドをゼロ値で設定したくない場合、構造体のフィールドの型をポインタにするなどの方法があります。
フィールドの型をポインタにする場合、マッピングされなかったフィールドにはnil
が設定されます。
type Student struct {
ID int
Name string
IsScholarship bool
Subjects []string
}
jsonData1 := []byte(`{
"FooBarNinja": true
}`)
var student1 Student
_ = json.Unmarshal(jsonData1, &student1)
fmt.Printf("%+v\n", student1)
==> {ID:0 Name: IsScholarship:false Subjects:[]}
// マッピングされないフィールドをnilにしたい場合
type Student2 struct {
ID *int
Name *string
IsScholarship *bool
Subjects *[]string
}
jsonData2 := []byte(`{
"FooBarNinja": true
}`)
var student2 Student2
_ = json.Unmarshal(jsonData2, &student2)
fmt.Printf("%+v\n", student2)
==> {ID:<nil> Name:<nil> IsScholarship:<nil> Subjects:<nil>}
JSONへの変換
Unmarshal関数は「JSONデータを他の値にマッピングする関数」ですが、同じjsonパッケージのMarshal関数は反対に「値をJSONへと変換する関数」です。
コード例にMarshal関数の使用方法を簡潔に記載しました。
より詳しく知りたい場合は以下のリンクを参照してください。
。
関連情報:json.Marshalの使用方法
type Person struct {
ID int
Height float64
}
// JSONから構造体へのマッピング
jsonData1 := []byte(`{
"id": 1,
"height": 176.5
}`)
var person1 Person
_ = json.Unmarshal(jsonData1, &person1)
fmt.Printf("%+v\n", person1)
==> {ID:1 Height:176.5}
// 構造体からJSONへの変換
encodedJson, err := json.Marshal(person1)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", encodedJson)
==> {"ID":1,"Height":176.5}