はじめに
YAMLをGo言語でパースしたり、逆に文字列に戻したりしたかったのですが、struct
定義をせずにやる方法をまとめた記事が見当たらなかったので、忘れない内に記事にします。
サンプルのソースコードは以下に置きました。
https://github.com/segurvita/yaml-encoding-practice
用意したYAML
以前の記事で作成したswagger.yamlを再利用します。
swagger: '2.0'
info:
description: これはアパートに関するAPIです。
version: 0.0.1
title: アパートAPI
paths:
'/rooms/{room-id}':
get:
summary: 部屋情報API
description: 指定されたroom-idの情報を返します
parameters:
- name: room-id
in: path
description: 取得したい部屋のID
required: true
type: integer
format: int64
responses:
'200':
description: OK
schema:
type: object
properties:
id:
type: integer
format: int64
example: 404
comment:
type: string
example: 404号室です。どこにも存在しない部屋かも。
サンプルコード
main.goの中身はこんな感じです。YAML文字列をオブジェクトに変換して、そのオブジェクトをYAML文字列に戻すということをしています。(意味はあまりありません。)
package main
import "fmt"
import "gopkg.in/yaml.v2"
func main() {
// 入力YAMLを定義
yamlInput := []byte(`
swagger: '2.0'
info:
description: これはアパートに関するAPIです。
version: 0.0.1
title: アパートAPI
paths:
'/rooms/{room-id}':
get:
summary: 部屋情報API
description: 指定されたroom-idの情報を返します
parameters:
- name: room-id
in: path
description: 取得したい部屋のID
required: true
type: integer
format: int64
responses:
'200':
description: OK
schema:
type: object
properties:
id:
type: integer
format: int64
example: 404
comment:
type: string
example: 404号室です。どこにも存在しない部屋かも。
`)
// YAMLをオブジェクトに変換
var objInput interface{}
err := yaml.Unmarshal(yamlInput, &objInput)
if err != nil {
fmt.Println("エラー: ", err)
}
// オブジェクトをYAMLに変換
yamlOutput, err := yaml.Marshal(&objInput)
if err != nil {
fmt.Println("エラー: ", err)
}
// 標準出力
fmt.Println("# ------------------------------------------------------------")
fmt.Println("# 入力YAML:")
fmt.Println("# ------------------------------------------------------------")
fmt.Println(string(yamlInput), "\n")
fmt.Println("# ------------------------------------------------------------")
fmt.Println("# オブジェクト:")
fmt.Println("# ------------------------------------------------------------")
fmt.Println(objInput, "\n")
fmt.Println("# ------------------------------------------------------------")
fmt.Println("# 出力YAML:")
fmt.Println("# ------------------------------------------------------------")
fmt.Println(string(yamlOutput), "\n")
}
解説
YAMLの解析処理にはgo-yaml
を使いました。
-
Unmarshal
がparse処理です。文字列をオブジェクトに変換します。 -
Marshal
がstringify処理です。オブジェクトを文字列に変換します。
Unmarshal
の第二引数にinterface{}
な変数を指定することで、struct
定義を回避しています。(便利!)
Marshal
も特に struct
を定義せずに使用できました。
出力結果
上記のコードを実行すると、以下のように出力されました。
info:
description: これはアパートに関するAPIです。
title: アパートAPI
version: 0.0.1
paths:
/rooms/{room-id}:
get:
description: 指定されたroom-idの情報を返します
parameters:
- description: 取得したい部屋のID
format: int64
in: path
name: room-id
required: true
type: integer
responses:
"200":
description: OK
schema:
properties:
comment:
example: 404号室です。どこにも存在しない部屋かも。
type: string
id:
example: 404
format: int64
type: integer
type: object
summary: 部屋情報API
swagger: "2.0"
同じ階層のキーがアルファベット順でソートされてしまいましたが、内容は入力したYAMLとまったく同一でした。
参考サイト
以下のサイトを参考にさせていただきました。
さいごに
意外と簡単にできて良かったです。