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