-
Notifications
You must be signed in to change notification settings - Fork 170
/
sigil.ex
84 lines (61 loc) · 1.91 KB
/
sigil.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
defmodule Jason.Sigil do
@doc ~S"""
Handles the sigil `~j` for JSON strings.
Calls `Jason.decode!/2` with modifiers mapped to options.
Given a string literal without interpolations, decodes the
string at compile-time.
## Modifiers
See `Jason.decode/2` for detailed descriptions.
* `a` - equivalent to `{:keys, :atoms}` option
* `A` - equivalent to `{:keys, :atoms!}` option
* `r` - equivalent to `{:strings, :reference}` option
* `c` - equivalent to `{:strings, :copy}` option
## Examples
iex> ~j"0"
0
iex> ~j"[1, 2, 3]"
[1, 2, 3]
iex> ~j'"string"'r
"string"
iex> ~j"{}"
%{}
iex> ~j'{"atom": "value"}'a
%{atom: "value"}
iex> ~j'{"#{:j}": #{~c'"j"'}}'A
%{j: "j"}
"""
defmacro sigil_j(term, modifiers)
defmacro sigil_j({:<<>>, _meta, [string]}, modifiers) when is_binary(string) do
Macro.escape(Jason.decode!(string, mods_to_opts(modifiers)))
end
defmacro sigil_j(term, modifiers) do
quote(do: Jason.decode!(unquote(term), unquote(mods_to_opts(modifiers))))
end
@doc ~S"""
Handles the sigil `~J` for raw JSON strings.
Decodes a raw string ignoring Elixir interpolations and
escape characters at compile-time.
## Examples
iex> ~J'"#{string}"'
"\#{string}"
iex> ~J'"\u0078\\y"'
"x\\y"
iex> ~J'{"#{key}": "#{}"}'a
%{"\#{key}": "\#{}"}
"""
defmacro sigil_J(term, modifiers)
defmacro sigil_J({:<<>>, _meta, [string]}, modifiers) when is_binary(string) do
Macro.escape(Jason.decode!(string, mods_to_opts(modifiers)))
end
@spec mods_to_opts(charlist) :: [Jason.decode_opt()]
defp mods_to_opts(modifiers) do
modifiers
|> Enum.map(fn
?a -> {:keys, :atoms}
?A -> {:keys, :atoms!}
?r -> {:strings, :reference}
?c -> {:strings, :copy}
m -> raise ArgumentError, "unknown sigil modifier #{<<?", m, ?">>}"
end)
end
end