40 lines
1.0 KiB
Elixir
40 lines
1.0 KiB
Elixir
defmodule Frenzy.JSONSchema do
|
|
@enforce_keys [:value, :schema]
|
|
defstruct [:value, :schema]
|
|
|
|
@type t() :: %__MODULE__{
|
|
value: map(),
|
|
schema: schema()
|
|
}
|
|
|
|
@type schema() ::
|
|
:string
|
|
| :boolean
|
|
| :integer
|
|
| {:list, schema()}
|
|
| %{required(String.t()) => schema()}
|
|
|
|
@spec coerce(schema :: schema(), value :: map() | list() | String.t()) :: map()
|
|
|
|
def coerce(:string, value) when is_binary(value), do: value
|
|
|
|
def coerce(:boolean, "true"), do: true
|
|
def coerce(:boolean, _), do: false
|
|
|
|
def coerce(:integer, value) when is_binary(value) do
|
|
{res, _} = Integer.parse(value)
|
|
res
|
|
end
|
|
|
|
def coerce({:list, list_type}, list_value) when is_list(list_value) do
|
|
Enum.map(list_value, &coerce(list_type, &1))
|
|
end
|
|
|
|
def coerce(schema, map_value) when is_map(schema) and is_map(map_value) do
|
|
Enum.reduce(schema, %{}, fn {key, value_schema}, acc ->
|
|
value = Map.fetch!(map_value, key)
|
|
Map.put(acc, key, coerce(value_schema, value))
|
|
end)
|
|
end
|
|
end
|