yamerl

YAML 1.2 and JSON parser in pure Erlang
授权协议 View license
开发语言 C/C++
所属分类 开发工具、 语法解析工具
软件类型 开源软件
地区 不详
投 递 者 邵阳辉
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

yamerl: YAML 1.2 and JSON parser in Erlang

Coverage StatusHex version

YAML is a human-friendly data serialization format. The specificationfor this language and many examples are available from the OfficialYAML web site. You may also want to check theYAML Wikipedia article.

yamerl is a pure Erlang applicationwhich is able to parse YAML 1.1 andYAML 1.2 documents, as wellas JSON documents. It only depends on standardErlang/OTP applications; no external dependency is required. It doesn'tuse native code either (neither port drivers nor NIFs).

yamerl can be used inside Elixir projects, like any other Erlanglibrary. You can find an example later in this README.

yamerl is distributed under the terms of the 2-clause BSD license;see LICENSE.

Integrate to your project

yamerl uses Rebar 3 as its build system soit can be integrated to many common build systems.

Rebar

yamerl is available as a Hex.pm package.Thus you can simply list it as a package dependency in your rebar.config:

{deps, [yamerl]}.

Erlang.mk

Erlang.mk knows about yamerl. You just need to add yamerl as adependency in your Makefile:

DEPS = yamerl

Mix

You can use yamerl in your Elixir project. yamerl is available as aHex.pm package. Thus you can simplylist its name in your mix.exs:

def project do
  [
    deps: [{:yamerl, "~> 0.8.0"}]
  ]
end

Getting started

Before using yamerl, the application must be started:

application:start(yamerl).

Now, one can use the yamerl_constr module to parse and construct alist of documents from:

  • an in-memory document (string or binary);
  • a regular file;
  • a stream.

Because a YAML input stream may contain multiple documents,yamerl_constr always returns a list of documents, even if the inputstream only contains one.

Parsing an in-memory document

yamerl_constr:string("Hello World!").
% List of documents; here, only one document.
[
 % Document #1; contains a single scalar.
 "Hello World!"
]

Here, the returned value is a list of documents containing one document.This document has a scalar as its sole node.

Parsing a file

Considering the following YAML file:

# applications.yaml
- application: kernel
  version:     2.15.3
  path:        /usr/local/lib/erlang/lib/kernel-2.15.3
- application: stdlib
  version:     1.18.3
  path:        /usr/local/lib/erlang/lib/stdlib-1.18.3
- application: sasl
  version:     2.2.1
  path:        /usr/local/lib/erlang/lib/sasl-2.2.1
yamerl_constr:file("applications.yaml").
% List of documents; again, only one document here.
[
 % List of mappings.
 [
  % Mapping, represented as a proplist: each entry has the form {Key, Value}.
  [
   {"application", "kernel"},
   {"version", "2.15.3"},
   {"path", "/usr/local/lib/erlang/lib/kernel-2.15.3"}
  ], [
   {"application", "stdlib"},
   {"version", "1.18.3"},
   {"path", "/usr/local/lib/erlang/lib/stdlib-1.18.3"}
  ], [
   {"application", "sasl"},
   {"version", "2.2.1"},
   {"path", "/usr/local/lib/erlang/lib/sasl-2.2.1"}
  ]
 ]
]

Parsing a stream

The developer is responsible for reading the stream and provide thechunks to yamerl.

% Initialize a new construction state. It takes a term describing the
% source; it may be any Erlang term.
Parser0 = yamerl_constr:new({file, "<stdin>"}),

% Read chunks and feed the parser. A new parser state is returned.
{continue, Parser1} = yamerl_constr:next_chunk(Parser0, Chunk1),
% ...
{continue, Parser2} = yamerl_constr:next_chunk(Parser1, Chunk2),

% When the stream ends, tell the parser it's the last chunk.
Documents = yamerl_constr:last_chunk(Parser2, Chunk3).

Simple vs. full document structures

yamerl_constr comes with two built-in modes:

  • It can output simple documents, eg. documents based on basic Erlangstructures (strings, numbers, lists, proplists). This is the defaultmode.
  • It can output detailed documents using records. These records carrymore information such as line/column, tag URI, YAML node type, moduleused to construct it, etc.

If we use the following YAML document:

# system.yaml
- os: FreeBSD
  version: 9.0-RELEASE-p3
  • Simple documents:
yamerl_constr:file("system.yaml").
% List of documents.
[
    % List of mappings.
    [
     % Mapping with two entries.
     [
      {"os", "FreeBSD"},
      {"version","9.0-RELEASE-p3"}
     ]
    ]
]
  • Full documents:
yamerl_constr:file("system.yaml", [{detailed_constr, true}]).
% List of documents.
[
    % Document with a list as its root node.
    {yamerl_doc,
     {yamerl_seq, yamerl_node_seq, "tag:yaml.org,2002:seq", [{line, 2}, {column, 1}], [
      % Mapping #1.
      {yamerl_map, yamerl_node_map, "tag:yaml.org,2002:map", [{line, 2}, {column, 3}], [
       {
        % Mapping entry #1.
        {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str", [{line, 2}, {column, 3}], "os"},
        {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str", [{line, 2}, {column, 7}], "FreeBSD"}
       }, {
        % Mapping entry #2.
        {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str", [{line, 3}, {column, 3}], "version"},
        {yamerl_str, yamerl_node_str, "tag:yaml.org,2002:str", [{line, 3}, {column, 12}], "9.0-RELEASE-p3"}
       }
      ]}
     ],
     1}
    }
]

Use yamerl in an Elixir project

Here is a complete example:

  1. You first need to add yamerl to the dependencies list in mix.exs:
# mix.exs, created with `mix new myapp` and updated to have `yamerl` as
# a dependency.
defmodule Myapp.Mixfile do
 use Mix.Project

 def project do
   [app: :myapp,
    version: "0.1.0",
    elixir: "~> 1.3",
    build_embedded: Mix.env == :prod,
    start_permanent: Mix.env == :prod,
    deps: deps()]
 end

 # Configuration for the OTP application
 #
 # Type "mix help compile.app" for more information
 def application do
   [applications: [:logger]]
 end

 # Dependencies can be Hex packages:
 #
 #   {:mydep, "~> 0.3.0"}
 #
 # Or git/path repositories:
 #
 #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
 #
 # Type "mix help deps" for more examples and options
 defp deps do
   [
     {:yamerl, "~> 0.4.0"}
   ]
 end
end
  1. Start the yamerl application and use the constructor, either insimple or detailed mode:
# lib/myapp.ex
defmodule Myapp do
 def simple(filename) do
   # The yamerl application must be started before any use of it.
   Application.start(:yamerl)

   :yamerl_constr.file(filename)
 end

 def detailed(filename) do
   # The yamerl application must be started before any use of it.
   Application.start(:yamerl)

   :yamerl_constr.file(filename, [:detailed_constr])
 end
end

Now let's use the Myapp module to parse the same YAML example file asabove:

# system.yaml
- os: FreeBSD
  version: 9.0-RELEASE-p3
  • Parsing in simple mode:
Myapp.simple("system.yaml")
# List of documents.
[
    # List of mappings.
    [
     # Mapping with two entries.
     [
      {'os', 'FreeBSD'},
      {'version', '9.0-RELEASE-p3'}
     ]
    ]
]
  • Parsing in detailed mode:
Myapp.detailed("system.yaml")
# List of documents.
[
    # Document with a list as its root node.
    yamerl_doc:
    {:yamerl_seq, :yamerl_node_seq, 'tag:yaml.org,2002:seq', [line: 2, column: 1],
     [
      # Mapping #1.
      {:yamerl_map, :yamerl_node_map, 'tag:yaml.org,2002:map', [line: 2, column: 3],
       [
        # Mapping entry #1.
        {
         {:yamerl_str, :yamerl_node_str, 'tag:yaml.org,2002:str', [line: 2, column: 3], 'os'},
         {:yamerl_str, :yamerl_node_str, 'tag:yaml.org,2002:str', [line: 2, column: 7], 'FreeBSD'}
        },
        # Mapping entry #2.
        {
         {:yamerl_str, :yamerl_node_str, 'tag:yaml.org,2002:str', [line: 3, column: 3], 'version'},
         {:yamerl_str, :yamerl_node_str, 'tag:yaml.org,2002:str', [line: 3, column: 12], '9.0-RELEASE-p3'}
        }
       ]
      }
     ],
     1
    }
]

Complete documentation

See https://hexdocs.pm/yamerl/ for a complete user guide and referencemanual.

相关阅读

相关文章

相关问答

相关文档