背景
こんにちは。エンジニアのKennieです。
以前の業務で、非公開フィールドを持つ構造体をシリアライズする必要がありました。その際にデフォルトでのMarshalJsonではシリアライズすることができなかったので、その際に学んだことを記載します。
デフォルトのMarshalJsonを使用したコード例
まずは、Goのデフォルトの MarshalJSON を使ったシンプルなコード例を見てみましょう。以下のコードでは、公開フィールドを持つ構造体がJSONとしてシリアライズされています。
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string
Age int
}
func main() {
p := Person{Name: "Alice", Age: 30}
data, err := json.Marshal(p)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(data))
}
出力結果
{"Name":"Alice","Age":30}
Ageを非公開にした場合
type Person struct {
Name string
age int
}
出力結果
{"Name":"Alice"}
このように、非公開フィールドはデフォルトのシリアライズ処理では無視されます。
非公開フィールドをシリアライズするためのカスタム MarshalJSON
非公開フィールドは、デフォルトの MarshalJSON ではシリアライズされません。そのため、カスタムの MarshalJSON を実装する必要があります。
package main
import (
"encoding/json"
"fmt"
)
type person struct {
Name string
age int // 非公開フィールド
}
func (p person) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Name string `json:"Name"`
Age int `json:"Age"`
}{
Name: p.Name,
Age: p.age,
})
}
func main() {
p := person{Name: "Alice", age: 30}
data, err := json.Marshal(p)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(data))
}
出力結果
{"Name":"Alice","Age":30}
ここでは age フィールドが非公開ですが、MarshalJSON メソッドをカスタム実装することで、非公開フィールドであっても JSON 出力に含めることができます。
実行の流れ
-
json.Marshal の呼び出し: json.Marshal 関数が呼ばれ、Person 構造体のインスタンスがシリアライズされます。これは Person 型のデータをJSON形式に変換するための関数です。
-
MarshalJSON のチェック: json.Marshal は Person 構造体が json.Marshaler インターフェースを実装しているかどうかを確認します。
-
カスタムメソッドの呼び出し: Person 構造体が json.Marshaler インターフェースを実装している場合、MarshalJSON メソッドが呼び出されます。このメソッドが返す結果がJSONとして出力されます。デフォルトのシリアライズ処理は無視され、Person 型に実装されたカスタムの MarshalJSON メソッドによるシリアライズが適用されます。
終わりに
開発の際に非公開フィールドを含む構造体をシリアライズする必要がありましたが、デフォルトの MarshalJSON メソッドではこれを実現できませんでした。そのため、カスタムの MarshalJSON メソッドを実装することで、非公開フィールドにアクセスし、シリアライズを行うことができました。今回の経験を通じて、MarshalJSON メソッドを用いたシリアライズ処理について理解が深まりました。