LoginSignup
12
7

More than 5 years have passed since last update.

Go言語でゆるふわにYAMLを使う

Posted at

はじめに

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とまったく同一でした。

参考サイト

以下のサイトを参考にさせていただきました。

さいごに

意外と簡単にできて良かったです。

12
7
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
12
7