exdn v2.1.1 Exdn
Exdn is a two-way translator between Elixir data structures and data following the edn specification; it wraps the erldn edn parser for Erlang, with some changes in the data formats.
Examples
iex> Exdn.to_elixir! "[1 :foo]"
[1, :foo]
iex> Exdn.to_elixir "{1 :foo, 2 :bar}"
{:ok, %{1 => :foo, 2 => :bar}}
iex> Exdn.from_elixir! %{1 => :foo, 2 => :bar}
"{1 :foo 2 :bar}"
iex> Exdn.from_elixir %{:foo => {:char, ?a}, {:char, ?b} => {:tag, :inst, "1985-04-12T23:20:50.52Z"} }
{:ok, "{:foo \a \b #inst "1985-04-12T23:20:50.52Z"}" }
Type mappings:
edn | Elixir generated by to_elixir functions (when no custom converter is provided) |
---|---|
integer | integer |
float | float |
boolean | boolean |
nil | nil (atom) |
char | string |
string | string |
list | tagged list {:list, [...]} |
vector | list |
map | map |
set | mapset |
symbol | tagged atom {:symbol, atom} |
tagged elements | call registered handler for that tag, fail if not found |
Elixir accepted by from_elixir functions | edn |
---|---|
integer | integer |
float | float |
boolean | boolean |
nil (atom) | nil |
tagged integer {:char, <integer>} | char |
string | string |
tagged list {:list, [...]} | list |
list | vector |
map | map |
struct | map |
mapset | set |
tagged atom {:symbol, atom} | symbol |
tagged tuple with tag and value {:tag, Symbol, Value} | tagged elements |
Summary
Functions
interprets a tagged expression using the tagged reversible representation and handlers passed in as a keyword list. Assumes the expression inside the tag has already been translated from edn
safe version of from_elixir!/1
— the edn string is returned as the second
element of a pair whose first element is :ok
— if there is an error the first
element will be :error
and the second the error that was raised
converts an Elixir data structure in the “reversible” format (see below) into an edn string. Will raise exceptions if the data structure cannot be converted
handlers for standard edn tagged expressions #inst and #uuid. If you need to supply your own custom handlers for other tags, you may wish to append them to this list of handlers
extracts a char (as a string) from the tagged reversible representation
extracts a list from the tagged reversible representation; does not operate at all on the contents of the extracted list
parses an edn string into an Elixir data structure, but does not throw
exceptions. The parse result is returned as the second element of a pair
whose first element is :ok
— if there is an error the first element will
be :error
and the second the error that was raised
parses an edn string into an Elixir data structure; this is not a reversible conversion as chars are converted to strings, and tagged expressions are interpreted. This function can throw exceptions; for example, if a tagged expression cannot be interpreted
parses an edn string into an Elixir data structure, but in a reversible way —
chars and tagged expressions are represented using tuples whose first element
is :char
or :tag
, respectively
Functions
interprets a tagged expression using the tagged reversible representation and handlers passed in as a keyword list. Assumes the expression inside the tag has already been translated from edn.
Example:
iex> tagged = {:tag, :foo, "blarg"}
iex> handler = fn(_tag, val, _converter, _handlers) -> val <> "-converted" end
iex> Exdn.evaluate_tagged_expr(tagged, [{:foo, handler}]
"blarg-converted"
safe version of from_elixir!/1
— the edn string is returned as the second
element of a pair whose first element is :ok
— if there is an error the first
element will be :error
and the second the error that was raised.
Example:
iex> Exdn.from_elixir %{:foo => {:char, ?a}, {:char, ?b} => {:tag, :inst, "1985-04-12T23:20:50.52Z"} }
{:ok, "{:foo \a \b #inst "1985-04-12T23:20:50.52Z"}" }
converts an Elixir data structure in the “reversible” format (see below) into an edn string. Will raise exceptions if the data structure cannot be converted.
Examples:
# The intermediate representation can be converted back to edn:
iex> Exdn.from_elixir! 41.2
"41.2"
iex> Exdn.from_elixir! :foo
":foo"
iex> Exdn.from_elixir! true
"true"
iex> Exdn.from_elixir! nil
"nil"
iex> Exdn.from_elixir! "asd"
""asd""
iex> Exdn.from_elixir! {:char, ?a}
"\a"
iex> Exdn.from_elixir! {:symbol, :foo}
"foo"
iex> Exdn.from_elixir! [1, :foo]
"[1 :foo]"
iex> Exdn.from_elixir! {:list, [1, :foo]}
"(1 :foo)"
iex> Exdn.from_elixir! MapSet.new([1, :foo])
"#{1 :foo}"
iex> Exdn.from_elixir! %{1 => :foo, 2 => :bar}
"{1 :foo 2 :bar}"
iex> Exdn.from_elixir! %SomeStruct{foo: 1, bar: 2}
"{:foo 1 :bar 2}"
iex> Exdn.from_elixir! {:tag, :inst, "1985-04-12T23:20:50.52Z"}
"#inst "1985-04-12T23:20:50.52Z""
handlers for standard edn tagged expressions #inst and #uuid. If you need to supply your own custom handlers for other tags, you may wish to append them to this list of handlers.
extracts a char (as a string) from the tagged reversible representation.
Example:
iex> Exdn.tagged_char_to_string {:char, ?a}
"a"
extracts a list from the tagged reversible representation; does not operate at all on the contents of the extracted list.
Example:
iex> Exdn.tagged_list_to_list {:list, [:foo]}
[:foo]
parses an edn string into an Elixir data structure, but does not throw
exceptions. The parse result is returned as the second element of a pair
whose first element is :ok
— if there is an error the first element will
be :error
and the second the error that was raised.
Examples:
iex> Exdn.to_elixir "{1 :foo, 2 :bar}"
{:ok, %{1 => :foo, 2 => :bar}}
iex> Exdn.to_elixir "{:foo, \a, \b #foo "blarg" }"
{:error, %RuntimeError{:message => "Handler not found for tag foo with tagged expression blarg"}}
parses an edn string into an Elixir data structure; this is not a reversible conversion as chars are converted to strings, and tagged expressions are interpreted. This function can throw exceptions; for example, if a tagged expression cannot be interpreted.
The second (optional) argument
The third (optional) argument allows you to supply your own handlers for the interpretation of tagged expressions. These should be in the form of a keyword list. The first element of each pair should be a keyword corresponding to the tag, and the second element a function of three parameters (tag, value, handlers) that handles the tagged values.
The one-argument version provides default handlers for #inst and #uuid.
Examples:
iex> Exdn.to_elixir! "41.2"
41.2
iex> Exdn.to_elixir! ":foo"
:foo
iex> Exdn.to_elixir! "true"
true
iex> Exdn.to_elixir! "nil"
nil
iex> Exdn.to_elixir! ""asd""
"asd"
# Char
iex> Exdn.to_elixir! "\a"
"a"
# Symbol
iex> Exdn.to_elixir! "foo"
{:symbol, :foo}
# edn vectors become Elixir lists:
iex> Exdn.to_elixir! "[1 :foo]"
[1, :foo]
# edn lists are always tagged. Since Datomic is a principal use of edn, and since lists are
# used in Datomic primarily for executable expressions rather than as data structures, we
# use Elixir lists to represent vectors and keep edn lists specially tagged:
iex> Exdn.to_elixir! "(1, :foo)"
{:list, [1, :foo]}
# edn sets become Elixir sets:
iex> Exdn.to_elixir! "#{1 \a 1}"
#MapSet<[1, "a"]>
# Maps become Elixir maps:
iex> Exdn.to_elixir! "{1 :foo, 2 :bar}"
%{1 => :foo, 2 => :bar}
# You can also transform maps to Elixir structs by providing your own converter in the second argument:
iex> defmodule FooStruct do
...> defstruct foo: "default"
...> end
iex> converter = fn map ->
...> case map do
...> %{:foo => _} -> struct(FooStruct, map)
...> anything_else -> anything_else
...> end
...> end
iex> Exdn.to_elixir! "{:foo 1, :bar 2}", converter
%FooStruct{foo: 1}
# Tagged expressions are converted. Standard converters for #inst and #uuid are included:
iex> Exdn.to_elixir! "#inst "1985-04-12T23:20:50.52Z""
%Calendar.DateTime{abbr: "UTC", day: 12, hour: 23, min: 20, month: 4, sec: 50,
std_off: 0, timezone: "Etc/UTC", usec: 520000, utc_off: 0, year: 1985}
iex> Exdn.to_elixir! "#uuid "f81d4fae-7dec-11d0-a765-00a0c91e6bf6""
"f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
# You can provide your own handlers for tagged expressions:
iex> handler = fn(_tag, val, _handlers) -> val <> "-converted" end
iex> Exdn.to_elixir! "#foo "blarg"", [{:foo, handler}]
"blarg-converted"
parses an edn string into an Elixir data structure, but in a reversible way —
chars and tagged expressions are represented using tuples whose first element
is :char
or :tag
, respectively.
Examples:
iex> Exdn.to_reversible( "\a" )
{:char, ?a}
iex> Exdn.to_reversible "#inst "1985-04-12T23:20:50.52Z""
{:tag, :inst, "1985-04-12T23:20:50.52Z"}
# An unknown tag raises no error when using the reversible conversion:
iex> Exdn.to_reversible "#foo "blarg""
{:tag, :foo, "blarg"}