Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

118 rindas
4.0 KiB

  1. defmodule Jiffy do
  2. @moduledoc """
  3. A JSON parser as a NIF.
  4. # Data Format
  5. | Elixir | -> JSON | -> Elixir |
  6. | ---------------------------- | ---------------- | ------- |
  7. | `nil` | `null` | `nil` |
  8. | `true` | `true` | `true` |
  9. | `false` | `false` | `false` |
  10. | `'hi'` | `[104, 105]` | `[104, 105]` |
  11. | `"hi"` | `"hi"` | `"hi"` |
  12. | `:hi` | `"hi"` | `"hi"` |
  13. | `1` | `1` | `1` |
  14. | `1.25` | `1.25` | `1.25` |
  15. | `[]` | `[]` | `[]` |
  16. | `[true, 1.0]` | `[true, 1.0]` | `[true, 1.0]` |
  17. | `%{"foo" => "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
  18. | `%{foo: "bar"}` | `{"foo": "bar"}` | `%{"foo" => "bar"}` |
  19. """
  20. @encode_options [:use_nil]
  21. @decode_options [:use_nil, :return_maps]
  22. @doc """
  23. Encode a value to JSON.
  24. # Unsupported structures
  25. * Encoding Keywords currently is not supported.
  26. * Encoding DateTime, Date or other Date-related Elixir structures will return
  27. `{:error, {:invalid_ejson, any}}`. If you want to encode them - you need to cast
  28. them to string before encoding.
  29. # Options
  30. * `:uescape` - Escapes UTF-8 sequences to produce a 7-bit clean output.
  31. * `:pretty` - Produce JSON using two-space indentation.
  32. * `:force_utf8` - Force strings to encode as UTF-8 by fixing broken
  33. surrogate pairs and/or using the replacement character to remove
  34. broken UTF-8 sequences in data.
  35. * `:escape_forward_slashes` - Escapes the `/` character which can be
  36. useful when encoding URLs in some cases.
  37. * `{:bytes_per_red, n}` - Refer to the `decode/2` options.
  38. * `{:bytes_per_iter, n}` - Refer to the `decode/2` options.
  39. # Examples
  40. iex> Jiffy.encode([1, 2, 3])
  41. {:ok, "[1,2,3]"}
  42. """
  43. @spec encode(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | {:error, any()}
  44. def encode(data, opts \\ []) do
  45. {:ok, encode!(data, opts)}
  46. catch
  47. {:error, reason} -> {:error, reason}
  48. end
  49. @doc """
  50. Encode a value to JSON, raises an exception on error.
  51. For list of options see `encode/2`.
  52. # Examples
  53. iex> Jiffy.encode!([1, 2, 3])
  54. "[1,2,3]"
  55. """
  56. @spec encode!(any, opts :: :jiffy.encode_option()) :: {:ok, any()} | no_return()
  57. def encode!(data, opts \\ []) do
  58. data
  59. |> :jiffy.encode(@encode_options ++ opts)
  60. |> :erlang.iolist_to_binary()
  61. end
  62. @doc """
  63. Decode JSON to a value.
  64. # Options
  65. * `:return_trailer` - If any non-whitespace is found after the first
  66. JSON term is decoded the return value of decode/2 becomes
  67. `{:has_trailer, first_term, rest_iodata}`. This is useful to
  68. decode multiple terms in a single binary.
  69. * `{:bytes_per_red, n}` where `n` >= 0 - This controls the number of
  70. bytes that Jiffy will process as an equivalent to a reduction. Each
  71. 20 reductions we consume 1% of our allocated time slice for the current
  72. process. When the Erlang VM indicates we need to return from the NIF.
  73. * `{:bytes_per_iter, n}` where `n` >= 0 - Backwards compatible option
  74. that is converted into the `bytes_per_red` value.
  75. # Examples
  76. iex> Jiffy.decode("[1,2,3]")
  77. {:ok, [1, 2, 3]}
  78. """
  79. @spec decode(String.t(), opts :: :jiffy.decode_option()) :: {:ok, any()} | {:error, atom()}
  80. def decode(data, opts \\ []) do
  81. {:ok, decode!(data, opts)}
  82. catch
  83. {:error, reason} -> {:error, reason}
  84. end
  85. @doc """
  86. Decode JSON to a value, raises an exception on error.
  87. For list of options see `decode/2`.
  88. # Examples
  89. iex> Jiffy.decode!("[1,2,3]")
  90. [1, 2, 3]
  91. """
  92. @spec decode!(String.t(), opts :: :jiffy.decode_option()) :: any() | no_return()
  93. def decode!(data, opts \\ []) do
  94. :jiffy.decode(data, @decode_options ++ opts)
  95. end
  96. end