Current section

Files

Jump to
xcribe lib xcribe json_schema.ex
Raw

lib/xcribe/json_schema.ex

defmodule Xcribe.JsonSchema do
@moduledoc false
@doc """
Return the type of given data
"""
def type_for(item) when is_number(item), do: "number"
def type_for(item) when is_binary(item), do: "string"
def type_for(item) when is_boolean(item), do: "boolean"
def type_for(item) when is_map(item), do: "object"
def type_for(item) when is_list(item), do: "array"
def type_for(_), do: "string"
@doc ~S"""
Return the format of given data
"""
def format_for(data) when is_float(data), do: "float"
def format_for(data) when is_integer(data), do: "int32"
def format_for(_), do: ""
@doc """
Basic implementation of JSON Schema specification (http://json-schema.org/)
### Options:
* `:title` - Include the schema title, default is `true`.
* `:example` - Include the schema example, default is `false`.
"""
def schema_for(data, opts \\ [title: true, example: true])
def schema_for(data, opts) when is_map(data) or is_list(data),
do: schema_object_for({nil, data}, opts)
def schema_for({title, data}, opts), do: schema_object_for({title, data}, opts)
@opt_no_title {:title, false}
@opt_example {:example, true}
defp schema_object_for({title, value}, opts) when is_map(value) do
%{type: "object"}
|> schema_add_title(title, @opt_no_title in opts)
|> schema_add_properties(value, opts)
end
defp schema_object_for({title, value}, opts) when is_list(value) do
%{type: "array"}
|> schema_add_title(title, @opt_no_title in opts)
|> schema_add_items(value, opts)
end
defp schema_object_for({title, value}, opts) do
%{type: type_for(value)}
|> schema_add_title(title, @opt_no_title in opts)
|> schema_add_format(format_for(value))
|> schema_add_example(value, @opt_example in opts)
end
defp schema_add_title(schema, nil, _active), do: schema
defp schema_add_title(schema, _title, true), do: schema
defp schema_add_title(schema, title, false), do: Map.put(schema, :title, title)
defp schema_add_format(schema, ""), do: schema
defp schema_add_format(schema, format), do: Map.put(schema, :format, format)
defp schema_add_example(schema, value, true), do: Map.put(schema, :example, value)
defp schema_add_example(schema, _value, false), do: schema
defp schema_add_properties(schema, value, opts) do
Map.put(schema, :properties, reduce_properties(value, opts))
end
defp reduce_properties(properties, opts) do
property_opts = Keyword.merge(opts, title: false)
Enum.reduce(properties, %{}, fn {title, value}, schema ->
Map.put(
schema,
title,
schema_object_for({:schema_add_properties, value}, property_opts)
)
end)
end
defp schema_add_items(schema, [], _opts), do: Map.put(schema, :items, %{type: "string"})
defp schema_add_items(schema, [value | _], opts) do
item_opts = Keyword.merge(opts, title: false)
Map.put(
schema,
:items,
schema_object_for({:schema_add_items, value}, item_opts)
)
end
end