jason.ex (7888B)
1 defmodule Jason do 2 @moduledoc """ 3 A blazing fast JSON parser and generator in pure Elixir. 4 """ 5 6 alias Jason.{Encode, Decoder, DecodeError, EncodeError, Formatter} 7 8 @type escape :: :json | :unicode_safe | :html_safe | :javascript_safe 9 @type maps :: :naive | :strict 10 11 @type encode_opt :: {:escape, escape} | {:maps, maps} | {:pretty, boolean | Formatter.opts()} 12 13 @type keys :: :atoms | :atoms! | :strings | :copy | (String.t() -> term) 14 15 @type strings :: :reference | :copy 16 17 @type floats :: :native | :decimals 18 19 @type objects :: :maps | :ordered_objects 20 21 @type decode_opt :: {:keys, keys} | {:strings, strings} | {:floats, floats} | {:objects, objects} 22 23 @doc """ 24 Parses a JSON value from `input` iodata. 25 26 ## Options 27 28 * `:keys` - controls how keys in objects are decoded. Possible values are: 29 30 * `:strings` (default) - decodes keys as binary strings, 31 * `:atoms` - keys are converted to atoms using `String.to_atom/1`, 32 * `:atoms!` - keys are converted to atoms using `String.to_existing_atom/1`, 33 * custom decoder - additionally a function accepting a string and returning a key 34 is accepted. 35 36 * `:strings` - controls how strings (including keys) are decoded. Possible values are: 37 38 * `:reference` (default) - when possible tries to create a sub-binary into the original 39 * `:copy` - always copies the strings. This option is especially useful when parts of the 40 decoded data will be stored for a long time (in ets or some process) to avoid keeping 41 the reference to the original data. 42 43 * `:floats` - controls how floats are decoded. Possible values are: 44 45 * `:native` (default) - Native conversion from binary to float using `:erlang.binary_to_float/1`, 46 * `:decimals` - uses `Decimal.new/1` to parse the binary into a Decimal struct with arbitrary precision. 47 48 * `:objects` - controls how objects are decoded. Possible values are: 49 50 * `:maps` (default) - objects are decoded as maps 51 * `:ordered_objects` - objects are decoded as `Jason.OrderedObject` structs 52 53 ## Decoding keys to atoms 54 55 The `:atoms` option uses the `String.to_atom/1` call that can create atoms at runtime. 56 Since the atoms are not garbage collected, this can pose a DoS attack vector when used 57 on user-controlled data. 58 59 ## Examples 60 61 iex> Jason.decode("{}") 62 {:ok, %{}} 63 64 iex> Jason.decode("invalid") 65 {:error, %Jason.DecodeError{data: "invalid", position: 0, token: nil}} 66 """ 67 @spec decode(iodata, [decode_opt]) :: {:ok, term} | {:error, DecodeError.t()} 68 def decode(input, opts \\ []) do 69 input = IO.iodata_to_binary(input) 70 Decoder.parse(input, format_decode_opts(opts)) 71 end 72 73 @doc """ 74 Parses a JSON value from `input` iodata. 75 76 Similar to `decode/2` except it will unwrap the error tuple and raise 77 in case of errors. 78 79 ## Examples 80 81 iex> Jason.decode!("{}") 82 %{} 83 84 iex> Jason.decode!("invalid") 85 ** (Jason.DecodeError) unexpected byte at position 0: 0x69 ("i") 86 87 """ 88 @spec decode!(iodata, [decode_opt]) :: term | no_return 89 def decode!(input, opts \\ []) do 90 case decode(input, opts) do 91 {:ok, result} -> result 92 {:error, error} -> raise error 93 end 94 end 95 96 @doc """ 97 Generates JSON corresponding to `input`. 98 99 The generation is controlled by the `Jason.Encoder` protocol, 100 please refer to the module to read more on how to define the protocol 101 for custom data types. 102 103 ## Options 104 105 * `:escape` - controls how strings are encoded. Possible values are: 106 107 * `:json` (default) - the regular JSON escaping as defined by RFC 7159. 108 * `:javascript_safe` - additionally escapes the LINE SEPARATOR (U+2028) 109 and PARAGRAPH SEPARATOR (U+2029) characters to make the produced JSON 110 valid JavaScript. 111 * `:html_safe` - similar to `:javascript_safe`, but also escapes the `/` 112 character to prevent XSS. 113 * `:unicode_safe` - escapes all non-ascii characters. 114 115 * `:maps` - controls how maps are encoded. Possible values are: 116 117 * `:strict` - checks the encoded map for duplicate keys and raises 118 if they appear. For example `%{:foo => 1, "foo" => 2}` would be 119 rejected, since both keys would be encoded to the string `"foo"`. 120 * `:naive` (default) - does not perform the check. 121 122 * `:pretty` - controls pretty printing of the output. Possible values are: 123 124 * `true` to pretty print with default configuration 125 * a keyword of options as specified by `Jason.Formatter.pretty_print/2`. 126 127 ## Examples 128 129 iex> Jason.encode(%{a: 1}) 130 {:ok, ~S|{"a":1}|} 131 132 iex> Jason.encode("\\xFF") 133 {:error, %Jason.EncodeError{message: "invalid byte 0xFF in <<255>>"}} 134 135 """ 136 @spec encode(term, [encode_opt]) :: 137 {:ok, String.t()} | {:error, EncodeError.t() | Exception.t()} 138 def encode(input, opts \\ []) do 139 case do_encode(input, format_encode_opts(opts)) do 140 {:ok, result} -> {:ok, IO.iodata_to_binary(result)} 141 {:error, error} -> {:error, error} 142 end 143 end 144 145 @doc """ 146 Generates JSON corresponding to `input`. 147 148 Similar to `encode/1` except it will unwrap the error tuple and raise 149 in case of errors. 150 151 ## Examples 152 153 iex> Jason.encode!(%{a: 1}) 154 ~S|{"a":1}| 155 156 iex> Jason.encode!("\\xFF") 157 ** (Jason.EncodeError) invalid byte 0xFF in <<255>> 158 159 """ 160 @spec encode!(term, [encode_opt]) :: String.t() | no_return 161 def encode!(input, opts \\ []) do 162 case do_encode(input, format_encode_opts(opts)) do 163 {:ok, result} -> IO.iodata_to_binary(result) 164 {:error, error} -> raise error 165 end 166 end 167 168 @doc """ 169 Generates JSON corresponding to `input` and returns iodata. 170 171 This function should be preferred to `encode/2`, if the generated 172 JSON will be handed over to one of the IO functions or sent 173 over the socket. The Erlang runtime is able to leverage vectorised 174 writes and avoid allocating a continuous buffer for the whole 175 resulting string, lowering memory use and increasing performance. 176 177 ## Examples 178 179 iex> {:ok, iodata} = Jason.encode_to_iodata(%{a: 1}) 180 iex> IO.iodata_to_binary(iodata) 181 ~S|{"a":1}| 182 183 iex> Jason.encode_to_iodata("\\xFF") 184 {:error, %Jason.EncodeError{message: "invalid byte 0xFF in <<255>>"}} 185 186 """ 187 @spec encode_to_iodata(term, [encode_opt]) :: 188 {:ok, iodata} | {:error, EncodeError.t() | Exception.t()} 189 def encode_to_iodata(input, opts \\ []) do 190 do_encode(input, format_encode_opts(opts)) 191 end 192 193 @doc """ 194 Generates JSON corresponding to `input` and returns iodata. 195 196 Similar to `encode_to_iodata/1` except it will unwrap the error tuple 197 and raise in case of errors. 198 199 ## Examples 200 201 iex> iodata = Jason.encode_to_iodata!(%{a: 1}) 202 iex> IO.iodata_to_binary(iodata) 203 ~S|{"a":1}| 204 205 iex> Jason.encode_to_iodata!("\\xFF") 206 ** (Jason.EncodeError) invalid byte 0xFF in <<255>> 207 208 """ 209 @spec encode_to_iodata!(term, [encode_opt]) :: iodata | no_return 210 def encode_to_iodata!(input, opts \\ []) do 211 case do_encode(input, format_encode_opts(opts)) do 212 {:ok, result} -> result 213 {:error, error} -> raise error 214 end 215 end 216 217 defp do_encode(input, %{pretty: true} = opts) do 218 case Encode.encode(input, opts) do 219 {:ok, encoded} -> {:ok, Formatter.pretty_print_to_iodata(encoded)} 220 other -> other 221 end 222 end 223 224 defp do_encode(input, %{pretty: pretty} = opts) when pretty !== false do 225 case Encode.encode(input, opts) do 226 {:ok, encoded} -> {:ok, Formatter.pretty_print_to_iodata(encoded, pretty)} 227 other -> other 228 end 229 end 230 231 defp do_encode(input, opts) do 232 Encode.encode(input, opts) 233 end 234 235 defp format_encode_opts(opts) do 236 Enum.into(opts, %{escape: :json, maps: :naive}) 237 end 238 239 defp format_decode_opts(opts) do 240 Enum.into(opts, %{keys: :strings, strings: :reference, floats: :native, objects: :maps}) 241 end 242 end