defmodule JsonSchema.Parser do @moduledoc """ Parses JSON schema files into an intermediate representation to be used for e.g. printing elm decoders. """ alias JsonSchema.Parser.{ErrorUtil, RootParser, SchemaResult} @doc """ Parses one or more JSON Schema files into a `SchemaResult`. """ @spec parse_schema_files([Path.t()]) :: SchemaResult.t() def parse_schema_files(schema_paths) do {ok_schemas, failed_schemas} = schema_paths |> Enum.reduce({[], []}, fn schema_path, {schemas, failed_schemas} -> case File.read(schema_path) do {:ok, schema} -> {[{schema_path, schema} | schemas], failed_schemas} {:error, _posix} -> {schemas, [schema_path | failed_schemas]} end end) if Enum.empty?(failed_schemas) do parse_schema_documents(ok_schemas) else parser_errors = failed_schemas |> Enum.map(fn schema_path -> ErrorUtil.could_not_read_file(schema_path) end) SchemaResult.new(%{}, [], parser_errors) end end @doc """ Parses one or more JSON Schema documents into a `SchemaResult`. """ @spec parse_schema_documents([{Path.t(), String.t()}]) :: SchemaResult.t() def parse_schema_documents(schema_path_document_pairs) do schema_path_document_pairs |> Enum.reduce(SchemaResult.new(), fn {schema_path, schema_document}, acc -> schema_document |> parse_schema_document(schema_path) |> SchemaResult.merge(acc) end) end @doc """ Parses a single JSON Schema documents into a `SchemaResult`. """ @spec parse_schema_document(String.t(), Path.t()) :: SchemaResult.t() def parse_schema_document(schema_document, schema_path) do case Jason.decode(schema_document) do {:ok, json} -> RootParser.parse_schema(json, schema_path) {:error, error} -> decode_error = {schema_path, [ErrorUtil.invalid_json(schema_path, error)]} SchemaResult.new(%{}, [], [decode_error]) end end end