yaml_elixir

repository·master·Indexed 41 days ago

https://github.com/kamillelonek/yaml-elixir

A YAML parser for Elixir that wraps the Erlang yamerl library. It provides functions to parse YAML from strings and files, such as read_from_string/1 and read_from_file/1, supports the ~y sigil for inlining YAML, and includes options for atom autodetection, resolving anchors and aliases, and converting maps to keyword lists.

Tokens
2.2K
Snippets
15
Records
16
Agent score
52%

What's inside yaml_elixir

  1. Enable atom autodetection for keys and values

    master

    By default, all keys and values are strings. To automatically convert keys and values starting with : into atoms, pass atoms: true to read_from_string/2 or read_from_file/2.

    Warning: Atoms are not garbage collected by the BEAM. Do not use this option with untrusted user-supplied input to avoid memory exhaustion attacks.

    yaml = """
      a: a
      :f: :atom
    """
    YamlElixir.read_from_string(yaml, atoms: true)
    # {:ok, %{:f => :atom, "a" => "a"}}
  2. Convert YAML maps to Elixir keyword lists

    master

    There are two ways to handle keyword lists:

    1. Global transformation: Pass maps_as_keywords: true to any read_* function to transform all maps in the document into keyword lists.

    2. Targeted transformation via tags: To convert only specific blocks, you must first register the YamlElixir.Node.KeywordList module with yamerl and then use the specific YAML tag in your document.

    Note: Do not use YAML flow style (e.g., {foo: bar}) with the keyword list tag; it is not supported by the parser.

    # 1. Global
    YamlElixir.read_from_string(yaml, maps_as_keywords: true)
    
    # 2. Targeted
    :yamerl_app.set_param(:node_mods, [YamlElixir.Node.KeywordList])
    
    # YAML content:
    # prod:
    #   foo: !<tag:yaml_elixir,2019:keyword_list>
    #     foo: bar
    #     bar: foo
  3. Use the ~y YAML Sigil

    master

    The YamlElixir.Sigil module provides the ~y sigil for inlining YAML within your Elixir code. You must import YamlElixir.Sigil to use it.

    Use the a modifier to enable atom autodetection for the inlined string.

    import YamlElixir.Sigil
    
    @config ~y"""
    debug: false
    port: 9200
    """
    
    # With atom autodetection
    ~y":answer: yes"a
  4. Parse a YAML string with read_from_string/1

    master

    Use YamlElixir.read_from_string/1 to convert a YAML-formatted string into an Elixir map. By default, keys and values are returned as strings.

    yaml = """
      a: a
      b: 1
      c: true
      d: ~
      e: nil
    """
    YamlElixir.read_from_string(yaml)
    # {:ok, %{"a" => "a", "b" => 1, "c" => true, "d" => nil, "e" => "nil"}}
  5. Resolve YAML anchors and aliases

    master

    To resolve YAML anchors (e.g., &foo) and merge keys (e.g., <<: *foo), pass merge_anchors: true to the parsing functions.

    yaml = """
    foo: &foo
      bar: 42
    baz:
      <<: *foo
    """
    YamlElixir.read_from_string(yaml, merge_anchors: true)
    # {:ok, %{"foo" => %{"bar" => 42}, "baz" => %{"bar" => 42}}}
  6. Handle missing YAML files with FileNotFoundError

    master

    If you attempt to parse a file that does not exist, the library raises a YamlElixir.FileNotFoundError. This exception contains a message field describing the file error.

    try
      YamlElixir.parse_file("non_existent.yaml")
    rescue
      %YamlElixir.FileNotFoundError{message: msg} ->
        IO.puts("Error: #{msg}")
    end
  7. Handle YAML parsing errors

    master

    When using the non-bang (!) versions of the parsing functions, errors are returned as {:error, reason} tuples. The library provides specific error types:

    • %YamlElixir.FileNotFoundError{message: string}: Raised when the specified file path cannot be opened.
    • %YamlElixir.ParsingError{message: string}: Raised when the YAML content is malformed or contains parsing errors from the underlying yamerl engine.
  8. Handle YAML parsing errors with ParsingError

    master

    When the YAML parser encounters invalid syntax, it raises a YamlElixir.ParsingError. This exception provides context about where the error occurred in the document. You can catch this exception to access the specific line, column, and error type to provide better feedback to users.

    If the error is caught, the message/0 function will return a string containing the error description and the location (e.g., "parsing error (line: 10, column: 5)").

    try
      YamlElixir.parse(yaml_string)
    rescue
      %YamlElixir.ParsingError{line: line, column: col, message: msg} ->
        IO.puts("Failed to parse YAML at line #{line}, col #{col}: #{msg}")
    end
  9. Parse a single YAML document from a file

    master

    Use YamlElixir.read_from_file/2 to parse a YAML file and return only the last document found in the file. If you want the operation to raise an error on failure, use YamlElixir.read_from_file!/2.

    # Returns {:ok, single_document}
    YamlElixir.read_from_file("config.yaml")
    
    # Raises on error
    YamlElixir.read_from_file!("config.yaml")