Current section
Files
Jump to
Current section
Files
lib/jason_structs.ex
defmodule Jason.Structs do
@moduledoc """
The main module of `Jason.Structs`.
It provides functions for encoding and decoding JSON to and from structs.
The `encode` functions are basically delegating to `Jason.encode`, as the `Jason.Encoder`
is automatically implemented for all `Jason.Structs.Struct` modules.
The `decode` functions are delegating to `Jason.Structs.Decoder`.
We can have:
defmodule Country do
use Jason.Structs.Struct
jason_struct do
field(:code, String.t(), enforce: true)
field(:name, String.t(), enforce: true)
end
end
this is a `Jason.Structs.Struct` now, so if we have the following JSON:
json = ~s(
{
"code": "bg",
"name": "Bulgaria"
}
)
By using:
Jason.Structs.decode!(json, Country)
we get:
%Country{code: "bg", name: "Bulgaria"}
And we can convert
country = %Country{code: "bg", name: "Bulgaria"}
to JSON like this:
country |> Jason.Structs.encode!(pretty: true) |> IO.puts()
{
"code": "bg",
"name": "Bulgaria"
}
"""
@doc """
Generates JSON corresponding to the `input`.
See [Jason.encode/2](https://hexdocs.pm/jason/Jason.html#encode/2) for more information,
as it delegates to it.
The `Jason.Structs.Struct` structs automatically implement the `Jason.Encoder` protocol with
a custom implementation, so all of them can be encoded to JSON.
Examples
defmodule Country do
use Jason.Structs.Struct
jason_struct do
field(:code, String.t(), enforce: true)
field(:name, String.t(), enforce: true)
end
end
iex> country = %Country{code: "bg", name: "Bulgaria"}
iex> Jason.Structs.encode(country)
{:ok, ~s({"code":"bg","name":"Bulgaria"})}
"""
@spec encode(term(), [Jason.encode_opt()]) ::
{:ok, String.t()} | {:error, EncodeError.t() | Exception.t()}
defdelegate encode(input, encode_opts \\ []), to: Jason
@doc """
Generates JSON corresponding to input.
Similar to `encode/1` except it will unwrap the error tuple and raise in case of errors.
See [Jason.encode!/2](https://hexdocs.pm/jason/Jason.html#encode!/2) for more information,
as it delegates to it.
The `Jason.Structs.Struct` structs automatically implement the `Jason.Encoder` protocol with
a custom implementation, so all of them can be encoded to JSON.
Examples
defmodule Country do
use Jason.Structs.Struct
jason_struct do
field(:code, String.t(), enforce: true)
field(:name, String.t(), enforce: true)
end
end
iex> country = %Country{code: "bg", name: "Bulgaria"}
iex> Jason.Structs.encode!(country)
~s({"code":"bg","name":"Bulgaria"})
"""
@spec encode!(term(), [Jason.encode_opt()]) :: String.t() | no_return()
defdelegate encode!(term, encode_opts \\ []), to: Jason
@doc """
Parses a JSON value from input iodata and if a `struct_module` is provided,
which is a `Jason.Structs.Struct` implementation, the parsed result will be an
instance of that struct.
By skipping the `struct_module` it works like the normal `Jason.decode` function.
It can parse all valid JSON values that way (numbers, lists, booleans, objects, strings, null).
Examples
defmodule Country do
use Jason.Structs.Struct
jason_struct do
field(:code, String.t(), enforce: true)
field(:name, String.t(), enforce: true)
end
end
iex> json = ~s({"name": "Bulgaria", "code": "bg"})
iex> Jason.Structs.decode(json, Country)
{:ok, %Country{code: "bg", name: "Bulgaria"}}
iex> json = ~s({"name": "Bulgaria", "code": "bg"})
iex> Jason.Structs.decode(json)
{:ok, %{code: "bg", name: "Bulgaria"}}
iex> json = "55"
iex> Jason.Structs.decode(json)
{:ok, 55}
iex> Jason.Structs.decode("invalid")
{:error, %Jason.DecodeError{data: "invalid", position: 0, token: nil}}
"""
@spec decode(iodata(), atom()) :: {:ok, term()} | {:error, DecodeError.t()}
defdelegate decode(iodata, struct_module \\ nil), to: Jason.Structs.Decoder
@doc """
Parses a JSON value from input iodata and if a `struct_module` is provided,
which is a `Jason.Structs.Struct` implementation, the parsed result will be an
instance of that struct.
Similar to `decode/2` except it will unwrap the error tuple and raise in case of errors.
By skipping the `struct_module` it works like the normal `Jason.decode!` function.
It can parse all valid JSON values that way (numbers, lists, booleans, objects, strings, null).
Examples
defmodule Country do
use Jason.Structs.Struct
jason_struct do
field(:code, String.t(), enforce: true)
field(:name, String.t(), enforce: true)
end
end
iex> json = ~s({"name": "Bulgaria", "code": "bg"})
iex> Jason.Structs.decode!(json, Country)
%Country{code: "bg", name: "Bulgaria"}
iex> json = ~s({"name": "Bulgaria", "code": "bg"})
iex> Jason.Structs.decode!(json)
%{code: "bg", name: "Bulgaria"}
iex> Jason.Structs.decode!("true")
true
iex> Jason.Structs.decode!("invalid")
** (Jason.DecodeError) unexpected byte at position 0: 0x69 ('i')
"""
@spec decode!(iodata(), atom()) :: term() | no_return()
def decode!(iodata, struct_module \\ nil) do
case decode(iodata, struct_module) do
{:ok, result} -> result
{:error, error} -> raise error
end
end
end