VOOZH about

URL: https://dev.to/segur/parsing-and-serializing-yaml-in-go-without-struct-definitions-3fob

⇱ Parsing and Serializing YAML in Go Without Struct Definitions - DEV Community


Introduction

I wanted to parse YAML and convert it back to a string in Go, but I couldn't find an article that showed how to do it without defining a struct. So I'm writing it down before I forget.

The sample source code is available here:
https://github.com/segurvita/yaml-encoding-practice

The YAML Used in This Example

I'm reusing a swagger.yaml from a previous article.

swagger: '2.0'
info:
 description: This is an API for apartments.
 version: 0.0.1
 title: Apartment API
paths:
 '/rooms/{room-id}':
 get:
 summary: Room Info API
 description: Returns information for the specified room-id
 parameters:
 - name: room-id
 in: path
 description: The ID of the room to retrieve
 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: Room 404. Maybe it doesn't exist anywhere.

Sample Code

Here is the content of main.go. It converts a YAML string into an object, then converts that object back into a YAML string — not particularly useful on its own, but good for demonstrating the approach.

package main

import "fmt"
import "gopkg.in/yaml.v2"

func main() {
 // Define the input YAML
 yamlInput := []byte(`
swagger: '2.0'
info:
 description: This is an API for apartments.
 version: 0.0.1
 title: Apartment API
paths:
 '/rooms/{room-id}':
 get:
 summary: Room Info API
 description: Returns information for the specified room-id
 parameters:
 - name: room-id
 in: path
 description: The ID of the room to retrieve
 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: Room 404. Maybe it doesn't exist anywhere.
 `)

 // Convert YAML to object
 var objInput interface{}
 err := yaml.Unmarshal(yamlInput, &objInput)
 if err != nil {
 fmt.Println("Error: ", err)
 }

 // Convert object to YAML
 yamlOutput, err := yaml.Marshal(&objInput)
 if err != nil {
 fmt.Println("Error: ", err)
 }

 // Print to stdout
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println("# Input YAML:")
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println(string(yamlInput), "\n")
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println("# Object:")
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println(objInput, "\n")
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println("# Output YAML:")
 fmt.Println("# ------------------------------------------------------------")
 fmt.Println(string(yamlOutput), "\n")
}

Explanation

I used go-yaml for YAML processing.

  • Unmarshal is the parse operation — it converts a string into an object.
  • Marshal is the stringify operation — it converts an object into a string.

By passing an interface{} variable as the second argument to Unmarshal, we avoid the need to define a struct. Very convenient!

Marshal also works without a struct definition.

Output

Running the code above produces the following output:

info:
 description: This is an API for apartments.
 title: Apartment API
 version: 0.0.1
paths:
 /rooms/{room-id}:
 get:
 description: Returns information for the specified room-id
 parameters:
 - description: The ID of the room to retrieve
 format: int64
 in: path
 name: room-id
 required: true
 type: integer
 responses:
 "200":
 description: OK
 schema:
 properties:
 comment:
 example: Room 404. Maybe it doesn't exist anywhere.
 type: string
 id:
 example: 404
 format: int64
 type: integer
 type: object
 summary: Room Info API
swagger: "2.0"

The keys at each level were sorted alphabetically, but the content is exactly the same as the input YAML.

References

Closing

Easier than I expected — glad it worked out!