defmodule JsonSchema.Parser.EnumParser do
@behaviour JsonSchema.Parser.ParserBehaviour
@moduledoc ~S"""
Parse a JSON schema enum type:
{
"type": "string",
"enum": ["none", "green", "orange", "blue", "yellow", "red"]
}
Into an `JsonSchema.Types.EnumType`.
"""
require Logger
alias JsonSchema.{Parser, Types}
alias Parser.{ErrorUtil, ParserResult, Util}
alias Types.EnumType
@doc ~S"""
Returns true if the json subschema represents an enum type.
## Examples
iex> type?(%{})
false
iex> type?(%{"enum" => ["red", "yellow", "green"]})
true
"""
@impl JsonSchema.Parser.ParserBehaviour
@spec type?(Types.schemaNode()) :: boolean
def type?(%{"enum" => values}) when is_list(values) and length(values) > 0, do: true
def type?(_schema_node), do: false
@doc """
Parses a JSON schema enum type into an `JsonSchema.Types.EnumType`.
"""
@impl JsonSchema.Parser.ParserBehaviour
@spec parse(
Types.schemaNode(),
URI.t(),
URI.t() | nil,
URI.t(),
String.t()
) :: ParserResult.t()
def parse(%{"enum" => values} = schema_node, _parent_id, id, path, name) do
description = Map.get(schema_node, "description")
default = Map.get(schema_node, "default")
type = parse_enum_type(values)
errors =
if default != nil && not Enum.member?(values, default) do
[ErrorUtil.invalid_enum(path, "default", values, default)]
else
[]
end
enum_type = %EnumType{
name: name,
description: description,
default: default,
path: path,
type: type,
values: values
}
enum_type
|> Util.create_type_dict(path, id)
|> ParserResult.new([], errors)
end
@spec parse_enum_type(nonempty_list(term)) :: EnumType.value_type_name()
defp parse_enum_type(values) do
first_value = hd(values)
cond do
is_binary(first_value) -> :string
is_integer(first_value) -> :integer
is_number(first_value) -> :number
end
end
end