Go 言語(以下 golang)で、JSON データのパース用に複数の構造体(以下
struct
)を組み合わせたい。つまり、構造体のインスタンスをマージするのではなく、構造体そのものをマージしたいのです。
JSON データをパースしたいのですが、JSON 側の仕様が整っていませんでした。つまり、微妙に異なるも、ほぼ同じ struct
を複数用意する必要がありました。
シンプルな構造体を組み合わせてダイナミック(動的)に struct
を作りたいのですが、ダイナミックと言っても reflection
などを使うレベルではなく、特定のフィールドの組み合わせのみで十分なレベルです。
「golang struct マージ」とググっても、シンプルなタイトルや用途の Qiita 記事がヒットしなかったので、自分のググラビリティとして。
TL; DR (今北産業)
Embedded Struct(構造体の埋め込み)でよかった。
-
微妙に違う構造の JSON データ
パースしたいデータ例data1 := `{ "hoge": "hoge hoge", "fuga": "fuga fuga" }` data2 := `{ "hoge": "hoge hoge hoge", "piyo": "piyo piyo" }`
-
組み合わせ用の小さな構造体
type Foo struct { Hoge string `json:"hoge"` } type Bar struct { Fuga string `json:"fuga"` } type Buz struct { Piyo string `json:"piyo"` }
-
適宜パターンを組み合わせてパース
mix := new(struct { Foo Bar }) if err := json.Unmarshal([]byte(data1), mix); err != nil { panic(err) }
このパターンは、シンプルな構造のデータをパースする場合には適してますが、メソッドを絡めたり、逆の JSON データ出力(Marshal
)といった、ちょっと複雑なことをしようとすると、すぐに限界がきます。
TS; DR
package main
import (
"encoding/json"
"fmt"
)
type Foo struct {
Hoge string `json:"hoge"`
}
type Bar struct {
Fuga string `json:"fuga"`
}
type Buz struct {
Piyo string `json:"piyo"`
}
func main() {
// 微妙に違う JSON データ
data1 := `{
"hoge": "hoge hoge",
"fuga": "fuga fuga"
}`
data2 := `{
"hoge": "hoge hoge hoge",
"piyo": "piyo piyo"
}`
// パターン1をパースしてプリント
mix1 := new(struct {
Foo
Bar
})
if err := json.Unmarshal([]byte(data1), mix1); err != nil {
panic(err)
}
fmt.Println("Mix1:", mix1.Hoge, mix1.Fuga)
// パターン2をパースしてプリント
mix2 := new(struct {
Foo
Buz
})
if err := json.Unmarshal([]byte(data2), mix2); err != nil {
panic(err)
}
fmt.Println("Mix2:", mix2.Hoge, mix2.Piyo)
// Output:
// Mix1: hoge hoge fuga fuga
// Mix2: hoge hoge hoge piyo piyo
}
- オンラインで動作をみる @ GoPlayground
参考文献
- Embedding | Effective Go @ go.dev
- How can I merge two structs in Golang? @ StackOverflow