Go 言語(以下 golang)で、データのパース用に複数の構造体(以下 struct)を組み合わせたい。

JSON データをパースしたいのですが、JSON 側の仕様が整っていないため、微妙に異なるも、ほぼ同じ struct を複数用意する必要がありました。

シンプルな構造体を組み合わせてダイナミック(動的)に struct を作りたいのですが、ダイナミックと言っても reflection などを使うレベルではなく string フィールドのみで十分なのです。

「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

广告
将在 10 秒后关闭
bannerAds