Go言語のJSONタグとハイフンの使用

By quonta 4月 7, 2024

Go言語のJSONタグについて

Go言語では、構造体のフィールドにjsonタグを使用することで、JSONのエンコードやデコードの挙動を制御することができます。これは、Goの標準ライブラリの一部であるencoding/jsonパッケージによって提供されています。

例えば、次のような構造体があるとします。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

この構造体のフィールドにはjsonタグが付けられており、これによりJSONのキー名を制御しています。つまり、この構造体をJSONにエンコードすると、フィールド名ではなくタグで指定したキー名が使用されます。

p := Person{Name: "Alice", Age: 20}
jsonBytes, _ := json.Marshal(p)
fmt.Println(string(jsonBytes))  // {"name":"Alice","age":20}

逆に、JSONをこの構造体にデコードすると、JSONのキー名とタグで指定した名前が一致するフィールドに値が格納されます。

var p Person
json.Unmarshal([]byte(`{"name":"Bob","age":30}`), &p)
fmt.Println(p)  // {Bob 30}

このように、Go言語のjsonタグを使用することで、JSONのエンコードやデコードの挙動を柔軟に制御することができます。これはAPIとのインターフェースを設計する際などに非常に便利です。次のセクションでは、特にハイフン(-)を使ったタグの挙動について詳しく見ていきましょう。

ハイフン(-)の挙動

Go言語のjsonタグでは、ハイフン(-)を使用することで特殊な挙動を制御することができます。具体的には、ハイフン(-)をタグの値として設定すると、そのフィールドはJSONへのエンコードやデコードの対象から除外されます。

以下に例を示します。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"-"`
}

この構造体では、Ageフィールドのjsonタグにハイフン(-)が設定されています。これにより、AgeフィールドはJSONへのエンコードやデコードの対象から除外されます。

p := Person{Name: "Alice", Age: 20}
jsonBytes, _ := json.Marshal(p)
fmt.Println(string(jsonBytes))  // {"name":"Alice"}

上記のコードでは、AgeフィールドがJSONにエンコードされません。同様に、JSONをこの構造体にデコードする際も、Ageフィールドは無視されます。

var p Person
json.Unmarshal([]byte(`{"name":"Bob","age":30}`), &p)
fmt.Println(p)  // {Bob 0}

このように、ハイフン(-)を使ったjsonタグは、特定のフィールドをJSONのエンコードやデコードの対象から除外する際に使用します。これは、一部のフィールドを内部的な用途に限定したい場合などに便利です。次のセクションでは、omitemptyオプションの挙動について詳しく見ていきましょう。

omitemptyオプションの挙動

Go言語のjsonタグでは、omitemptyオプションを使用することで、フィールドの値がゼロ値の場合にJSONへのエンコードを省略することができます。これは、不要なデータを排除してJSONをコンパクトにする際に便利です。

以下に例を示します。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age,omitempty"`
}

この構造体では、Ageフィールドのjsonタグにomitemptyオプションが設定されています。これにより、Ageフィールドの値がゼロ値(この場合は0)のとき、そのフィールドはJSONへのエンコードから除外されます。

p := Person{Name: "Alice"}
jsonBytes, _ := json.Marshal(p)
fmt.Println(string(jsonBytes))  // {"name":"Alice"}

上記のコードでは、Ageフィールドがゼロ値なので、JSONにエンコードされません。しかし、Ageフィールドに非ゼロ値を設定すると、そのフィールドはJSONにエンコードされます。

p := Person{Name: "Bob", Age: 30}
jsonBytes, _ := json.Marshal(p)
fmt.Println(string(jsonBytes))  // {"name":"Bob","age":30}

このように、omitemptyオプションは、フィールドの値がゼロ値の場合にJSONへのエンコードを省略するために使用します。これは、オプショナルなデータを扱う際や、データのサイズを最小限に抑えたい場合などに便利です。次のセクションでは、エンコーディングとデコーディング時の挙動について詳しく見ていきましょう。

エンコーディングとデコーディング時の挙動

Go言語のjsonタグは、JSONのエンコーディング(変換)とデコーディング(解析)の挙動を制御します。具体的には、タグで指定した名前がJSONのキー名として使用され、そのフィールドの値がJSONの値として使用されます。

エンコーディング

エンコーディングは、Goの構造体をJSONに変換するプロセスです。このとき、jsonタグで指定した名前がJSONのキー名として使用されます。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

p := Person{Name: "Alice", Age: 20}
jsonBytes, _ := json.Marshal(p)
fmt.Println(string(jsonBytes))  // {"name":"Alice","age":20}

上記のコードでは、Nameフィールドの値(”Alice”)が"name"キーの値として、Ageフィールドの値(20)が"age"キーの値としてJSONにエンコードされています。

デコーディング

デコーディングは、JSONをGoの構造体に解析するプロセスです。このとき、JSONのキー名とjsonタグで指定した名前が一致するフィールドに、JSONの値が格納されます。

var p Person
json.Unmarshal([]byte(`{"name":"Bob","age":30}`), &p)
fmt.Println(p)  // {Bob 30}

上記のコードでは、"name"キーの値(”Bob”)がNameフィールドに、"age"キーの値(30)がAgeフィールドに格納されています。

このように、Go言語のjsonタグを使用することで、JSONのエンコーディングとデコーディングの挙動を制御することができます。これはAPIとのインターフェースを設計する際などに非常に便利です。次のセクションでは、実際のコード例を通じてこれらの概念を具体的に理解していきましょう。

実際のコード例

それでは、これまでに説明したjsonタグの各機能を組み合わせた実際のコード例を見てみましょう。

package main

import (
    "encoding/json"
    "fmt"
)

type Employee struct {
    Name     string `json:"name"`
    Age      int    `json:"age,omitempty"`
    Position string `json:"-"`
}

func main() {
    e := Employee{Name: "Alice", Age: 0, Position: "Engineer"}

    // エンコーディング
    jsonBytes, _ := json.Marshal(e)
    fmt.Println(string(jsonBytes))  // {"name":"Alice"}

    // デコーディング
    var e2 Employee
    json.Unmarshal([]byte(`{"name":"Bob","age":30,"position":"Manager"}`), &e2)
    fmt.Println(e2)  // {Bob 0 }
}

このコードでは、Employeeという構造体を定義しています。この構造体にはNameAgePositionという3つのフィールドがあり、それぞれにjsonタグが付けられています。

  • Nameフィールドのjsonタグは"name"となっており、このフィールドはJSONのキー名"name"としてエンコードされます。
  • Ageフィールドのjsonタグは"age,omitempty"となっており、このフィールドはゼロ値の場合にエンコードから除外されます。
  • Positionフィールドのjsonタグは"-"となっており、このフィールドはエンコードやデコードの対象から完全に除外されます。

このように、Go言語のjsonタグを使用することで、JSONのエンコーディングとデコーディングの挙動を細かく制御することができます。これはAPIとのインターフェースを設計する際などに非常に便利です。また、これらの機能を理解しておくと、他人が書いたコードを読む際にも役立ちます。この記事が、Go言語のjsonタグの理解に少しでもお役に立てれば幸いです。次回もお楽しみに!

By quonta

Related Post

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です