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?

More than 3 years have passed since last update.

[Go] YAMLファイルを埋め込み構造体に読み込む

Last updated at Posted at 2021-07-13

以前、Go言語でYAMLファイルを埋め込み構造体に読み込もうとした際に、JSONを読み込むのと同じように実装したらうまく読み込めなかったことがあった。
その時調べた内容をまとめておく。

結論

このようなYAMLファイルがあった場合、下記のように構造体の埋め込みフィールドにinlineタグをつけることで埋め込み構造体に読み込むことができる。

YAMLファイル

# tmp.yaml
wheels: 4
tons: 10

読み込むためのコード

package main

import (
	"fmt"
	"os"

	"gopkg.in/yaml.v2"
)

type Car struct {
	Wheels int `yaml:"wheels"`
}

type Truck struct {
	// 埋め込み のフィールドに 'inline' タグをつける
	Car  `yaml:",inline"`
	Tons int `yaml:"tons"`
}

func main() {
	truck := Truck{}
	b, _ := os.ReadFile("tmp.yaml")
	yaml.Unmarshal(b, &truck)
	fmt.Printf("Wheels: %+v\n", truck.Wheels)
	fmt.Printf("Tons: %v\n", truck.Tons)
}

下記が実行結果。

$ go run main.go
Wheels: 4
Tons: 10

そもそもJSONではもっと簡単

JSONではタグを気にする必要なく埋め込み構造体へ読み込み可能。

読み込み対象のJSONファイル

# tmp.json
{
    "wheels": 4,
    "tons": 10
}

サンプルコード

package main

import (
	"encoding/json"
	"fmt"
	"os"
)

type Car struct {
	Wheels int `json:"wheels"`
}

type Truck struct {
	Car // タグが必要ない
	Tons int `json:"tons"`
}

func main() {
	truck := Truck{}
	b, _ := os.ReadFile("tmp.json")
	json.Unmarshal(b, &truck)
	fmt.Printf("Wheels: %+v\n", truck.Wheels)
	fmt.Printf("Tons: %v\n", truck.Tons)
}

実行結果

$ go run main.go
Wheels: 4
Tons: 10

YAMLでも同じようにすると?

構造体を下記のように変更してYAMLファイルを読み込んでみる。

type Car struct {
	Wheels int `yaml:"wheels"`
}

type Truck struct {
	Car // JSONと同様にタグなしにしてみる
	Tons int `yaml:"tons"`
}

実行結果

$ go run main.go
Wheels: 0
Tons: 10

上記のようにWheelsが読み込めていない(0なのはintの初期値なため)。

ではどうすればよい?

Go言語は大体の場合、ドキュメント見れば対処法や原因が書いてある。
なので今回もyaml.v2パッケージのドキュメントを見に行くとinlineタグについて下記の記載がある。

Inline the field, which must be a struct or a map,
causing all of its fields or keys to be processed as if
they were part of the outer struct. For maps, keys must
not conflict with the yaml keys of other struct fields.

yaml · pkg.go.dev

要はinlineタグをつけるとその構造体のフィールドはその構造体の上位の構造体のフィールドとして扱われるとのこと。

例として、inlineタグを使用している下記構造体があったとする。

type Car struct {
	Wheels int `yaml:"wheels"`
}

type Truck struct {
	Car `yaml:",inline"` // inline タグを追加
	Tons int `yaml:"tons"`
}

これは、yaml.v2からすると下記と同等となる。

type Truck struct {
	Wheels int `yaml:"wheels"`
	Tons int `yaml:"tons"`
}

そのため、inlineタグを付けることによって埋め込み構造体にYAMLファイルを読み込むことができるようになる。

というわけで、これで埋め込み構造体にYAMLファイルを読み込むことができるようになった。

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?