Search code examples
crystal-lang

How to read a YAML file into a Hash


I have a requirement to read a YAML config file from disk into memory as a Hash in Crystal. (I am aware of this discussion on the topic in the mailing list, although I find it a bit confusing.)

The YAML file I am trying to read is a fairly simple config file:

---
:excludes:
  - Stage
  - Class
  - Anchor
  - Notify
  - Node
  - /::/
:only_include: []
:md5sums: false
:class_name: null
:catalog_file: null
:output_file: spec/classes/init_spec.rb
:compile_test: true
:setup: {}

A code example showing how to read a YAML config file from disk into a Hash using Crystal 0.25 would be very helpful.


Solution

  • Here's the best way to do it.

        require "yaml"
    
        class Config
          include YAML::Serializable
    
          @[YAML::Field(key: ":excludes")]
          property excludes : Array(String)
    
          @[YAML::Field(key: ":only_include")]
          property only_include : Array(String)
    
          @[YAML::Field(key: ":md5sums")]
          property md5sums : Bool
    
          @[YAML::Field(key: ":class_name")]
          property class_name : String?
    
          @[YAML::Field(key: ":catalog_file")]
          property catalog_file : String?
    
          @[YAML::Field(key: ":output_file")]
          property output_file : String
    
          @[YAML::Field(key: ":compile_test")]
          property compile_test : Bool
    
          @[YAML::Field(key: ":setup")]
          property setup : Hash(String, String)
        end
    
        yaml = <<-YAML
        :excludes:
          - Stage
          - Class
          - Anchor
          - Notify
          - Node
          - /::/
        :only_include: []
        :md5sums: false
        :class_name: null
        :catalog_file: null
        :output_file: spec/classes/init_spec.rb
        :compile_test: true
        :setup: {}
        YAML
    
        p Config.from_yaml(yaml)
    

    Just note that YAML in Crystal currently does not support creating a Regex from YAML, so you'll probably want to do that after you parse it (it's a bit tricky with a converter).