25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

118 lines
4.0 KiB

defmodule Jiffy do
@moduledoc """
A JSON parser as a NIF.
# Data Format
| Elixir | -> JSON | -> Elixir |
| ---------------------------- | ---------------- | ------- |
| `nil` | `null` | `nil` |
| `true` | `true` | `true` |
| `false` | `false` | `false` |
| `'hi'` | `[104, 105]` | `[104, 105]` |
| `"hi"` | `"hi"` | `"hi"` |
| `:hi` | `"hi"` | `"hi"` |
| `1` | `1` | `1` |
| `1.25` | `1.25` | `1.25` |
| `[]` | `[]` | `[]` |
| `[true, 1.0]` | `[true, 1.0]` | `[true, 1.0]` |
| `%{"foo" => "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
| `%{foo: "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
"""
@encode_options [:use_nil]
@decode_options [:use_nil, :return_maps]
@doc """
Encode a value to JSON.
# Unsupported structures
* Encoding Keywords currently is not supported.
* Encoding DateTime, Date or other Date-related Elixir structures will return
`{:error, {:invalid_ejson, any}}`. If you want to encode them - you need to cast
them to string before encoding.
# Options
* `:uescape` - Escapes UTF-8 sequences to produce a 7-bit clean output.
* `:pretty` - Produce JSON using two-space indentation.
* `:force_utf8` - Force strings to encode as UTF-8 by fixing broken
surrogate pairs and/or using the replacement character to remove
broken UTF-8 sequences in data.
* `:escape_forward_slashes` - Escapes the `/` character which can be
useful when encoding URLs in some cases.
* `{:bytes_per_red, n}` - Refer to the `decode/2` options.
* `{:bytes_per_iter, n}` - Refer to the `decode/2` options.
# Examples
iex> Jiffy.encode([1, 2, 3])
{:ok, "[1,2,3]"}
"""
@spec encode(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | {:error, any()}
def encode(data, opts \\ []) do
{:ok, encode!(data, opts)}
catch
{:error, reason} -> {:error, reason}
end
@doc """
Encode a value to JSON, raises an exception on error.
For list of options see `encode/2`.
# Examples
iex> Jiffy.encode!([1, 2, 3])
"[1,2,3]"
"""
@spec encode!(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | no_return()
def encode!(data, opts \\ []) do
data
|> :jiffy.encode(@encode_options ++ opts)
|> :erlang.iolist_to_binary()
end
@doc """
Decode JSON to a value.
# Options
* `:return_trailer` - If any non-whitespace is found after the first
JSON term is decoded the return value of decode/2 becomes
`{:has_trailer, first_term, rest_iodata}`. This is useful to
decode multiple terms in a single binary.
* `{:bytes_per_red, n}` where `n` >= 0 - This controls the number of
bytes that Jiffy will process as an equivalent to a reduction. Each
20 reductions we consume 1% of our allocated time slice for the current
process. When the Erlang VM indicates we need to return from the NIF.
* `{:bytes_per_iter, n}` where `n` >= 0 - Backwards compatible option
that is converted into the `bytes_per_red` value.
# Examples
iex> Jiffy.decode("[1,2,3]")
{:ok, [1, 2, 3]}
"""
@spec decode(String.t(), opts :: :jiffy.decode_option()) :: {:ok, any()} | {:error, atom()}
def decode(data, opts \\ []) do
{:ok, decode!(data, opts)}
catch
{:error, reason} -> {:error, reason}
end
@doc """
Decode JSON to a value, raises an exception on error.
For list of options see `decode/2`.
# Examples
iex> Jiffy.decode!("[1,2,3]")
[1, 2, 3]
"""
@spec decode!(String.t(), opts :: :jiffy.decode_option()) :: any() | no_return()
def decode!(data, opts \\ []) do
:jiffy.decode(data, @decode_options ++ opts)
end
end