Packages
jsv
0.11.2
0.21.2
0.21.1
0.21.0
0.20.0
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.3
0.18.2
0.18.1
0.18.0
0.17.1
0.17.0
0.16.0
0.15.2
0.15.1
0.15.0
0.14.0
0.13.1
0.13.0
0.12.0
0.11.5
0.11.4
0.11.3
retired
0.11.2
0.11.1
0.11.0
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
A JSON Schema Validator with complete support for the latest specifications.
Current section
Files
Jump to
Current section
Files
lib/jsv/vocabulary/cast.ex
defmodule JSV.Vocabulary.Cast do
alias JSV.Helpers.StringExt
alias JSV.Validator
use JSV.Vocabulary,
# Priority is meaningless here as this vocabulary is handled by the library
# core. But it takes precedences over all other vocabularies when registering
# a cast during validation, so we mark it as zero.
priority: :internal
@moduledoc false
@impl true
def init_validators([]) do
%{}
end
take_keyword :"jsv-cast", [module_str, arg], vds, builder, _ do
module = unwrap_ok(StringExt.safe_string_to_existing_module(module_str))
{Map.put(vds, :"jsv-cast", {module, arg}), builder}
end
ignore_any_keyword()
@impl true
def finalize_validators(map) do
case map_size(map) do
0 -> :ignore
_ -> map
end
end
@impl true
def validate(data, %{"jsv-cast": {module, arg}}, vctx) do
cond do
Validator.error?(vctx) ->
{:ok, data, vctx}
vctx.opts[:cast] ->
call_cast(module, arg, data, vctx)
:other ->
{:ok, data, vctx}
end
end
defp call_cast(module, arg, data, vctx) do
case module.__jsv__(arg, data) do
{:ok, new_data} ->
{:ok, new_data, vctx}
{:error, reason} ->
{:error,
JSV.Validator.__with_error__(__MODULE__, vctx, :"jsv-cast", data, module: module, reason: reason, arg: arg)}
end
rescue
e in [UndefinedFunctionError, FunctionClauseError] ->
case e do
%{module: ^module, function: :__jsv__} ->
{:error,
JSV.Validator.__with_error__(__MODULE__, vctx, :"bad-cast", data, module: module, reason: e, arg: arg)}
_ ->
reraise e, __STACKTRACE__
end
end
@impl true
def format_error(:"jsv-cast", args, data) do
if function_exported?(args.module, :format_error, 3) do
case args.module.format_error(args.arg, args.reason, data) do
message when is_binary(message) -> {:cast, message}
other -> other
end
else
{:cast, "cast failed"}
end
end
def format_error(:"bad-cast", _args, _data) do
{:cast, "invalid cast"}
end
end