0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Golang】複数の struct をマージする【小さな構造体をダイナミックに組み合わせたい】

Last updated at Posted at 2023-08-08

Go 言語(以下 golang)で、JSON データのパース用に複数の構造体(以下 struct)を組み合わせたい。つまり、構造体のインスタンスをマージするのではなく、構造体そのものをマージしたいのです。

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

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

「golang struct マージ」とググっても、シンプルなタイトルや用途の Qiita 記事がヒットしなかったので、自分のググラビリティとして。

TL; DR (今北産業)

Embedded Struct(構造体の埋め込み)でよかった。

  1. 微妙に違う構造の JSON データ

    パースしたいデータ例
    data1 := `{
        "hoge": "hoge hoge",
        "fuga": "fuga fuga"
    }`
    
    data2 := `{
        "hoge": "hoge hoge hoge",
        "piyo": "piyo piyo"
    }`
    
  2. 組み合わせ用の小さな構造体

    type Foo struct {
    	Hoge string `json:"hoge"`
    }
    
    type Bar struct {
    	Fuga string `json:"fuga"`
    }
    
    type Buz struct {
    	Piyo string `json:"piyo"`
    }
    
  3. 適宜パターンを組み合わせてパース

    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
}

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?