Packages
A library for parsing, inspecting and manipulating JSON Schema documents.
Current section
Files
Jump to
Current section
Files
lib/parser/object_parser.ex
defmodule JsonSchema.Parser.ObjectParser do
@behaviour JsonSchema.Parser.ParserBehaviour
@moduledoc ~S"""
Parses a JSON schema object type:
{
"type": "object",
"properties": {
"color": {
"$ref": "#/color"
},
"title": {
"type": "string"
},
"radius": {
"type": "number"
}
},
"required": [ "color", "radius" ]
}
Into an `JsonSchema.Types.ObjectType`
"""
require Logger
alias JsonSchema.{Parser, TypePath, Types}
alias Parser.{ParserResult, Util}
alias Types.ObjectType
@doc ~S"""
Returns true if the json subschema represents an allOf type.
## Examples
iex> type?(%{})
false
iex> an_object = %{"properties" => %{"name" => %{"type" => "string"}}}
iex> type?(an_object)
true
"""
@impl JsonSchema.Parser.ParserBehaviour
@spec type?(map) :: boolean
def type?(schema_node) do
properties = schema_node["properties"]
is_map(properties)
end
@doc ~S"""
Parses a JSON schema object type into an `JsonSchema.Types.ObjectType`.
"""
@impl JsonSchema.Parser.ParserBehaviour
@spec parse(Types.schemaNode(), URI.t(), URI.t(), TypePath.t(), String.t()) ::
ParserResult.t()
def parse(schema_node, parent_id, id, path, name) do
required = Map.get(schema_node, "required", [])
child_path = TypePath.add_child(path, "properties")
child_types_result =
schema_node
|> Map.get("properties")
|> parse_child_types(parent_id, child_path)
type_dict = create_property_dict(child_types_result.type_dict, child_path)
object_type = ObjectType.new(name, path, type_dict, required)
object_type
|> Util.create_type_dict(path, id)
|> ParserResult.new()
|> ParserResult.merge(child_types_result)
end
@spec parse_child_types(map, URI.t(), TypePath.t()) :: ParserResult.t()
defp parse_child_types(node_properties, parent_id, child_path) do
init_result = ParserResult.new()
node_properties
|> Enum.reduce(init_result, fn {child_name, child_node}, acc_result ->
child_types =
Util.parse_type(child_node, parent_id, child_path, child_name)
ParserResult.merge(acc_result, child_types)
end)
end
@doc ~S"""
Creates a property dictionary based on a type dictionary and a type path.
## Examples
iex> type_dict = %{}
...> path = JsonSchema.TypePath.from_string("#")
...> JsonSchema.Parser.ObjectParser.create_property_dict(type_dict, path)
%{}
"""
@spec create_property_dict(Types.typeDictionary(), TypePath.t()) ::
Types.propertyDictionary()
def create_property_dict(type_dict, path) do
type_dict
|> Enum.reduce(%{}, fn {child_path, child_type}, acc_property_dict ->
child_type_path = TypePath.add_child(path, child_type.name)
if child_type_path == TypePath.from_string(child_path) do
child_property_dict = %{child_type.name => child_type_path}
Map.merge(acc_property_dict, child_property_dict)
else
acc_property_dict
end
end)
end
end