Skip to content

Commit

Permalink
Support anonymous functions as custom validator function
Browse files Browse the repository at this point in the history
  • Loading branch information
arjan committed Nov 10, 2023
1 parent 7d7015c commit 72184a0
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ ExJsonSchema.Schema.resolve(%{"format" => "custom"}, custom_format_validator: {M

The configured function is called with the arguments `(format, data)` and is expected to return `true`, `false` or a `{:error, %Error.Format{expected: "something"}}` tuple, depending whether the data is valid for the given format. For compatibility with JSON schema, it is expected to return `true` when the format is unknown by your callback function.

The custom function can also be an anonymous function:

```elixir
ExJsonSchema.Schema.resolve(%{"format" => "custom"}, custom_format_validator: fn format, data -> true end)
```

[format-spec]: https://json-schema.org/understanding-json-schema/reference/string.html#format

## License
Expand All @@ -180,5 +186,5 @@ Released under the [MIT license](https://github.com/jonasschmidt/ex_json_schema/

## TODO

* Add some source code documentation
* Enable providing JSON for known schemata at resolve time
- Add some source code documentation
- Enable providing JSON for known schemata at resolve time
13 changes: 11 additions & 2 deletions lib/ex_json_schema/validator/format.ex
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ defmodule ExJsonSchema.Validator.Format do
defp do_validate(%Root{custom_format_validator: nil}, format, data) do
case Application.fetch_env(:ex_json_schema, :custom_format_validator) do
:error -> []
{:ok, validator} when is_function(validator, 2) -> validate_with_custom_validator(validator, format, data)
{:ok, validator = {_mod, _fun}} -> validate_with_custom_validator(validator, format, data)
end
end
Expand All @@ -107,8 +108,16 @@ defmodule ExJsonSchema.Validator.Format do
validate_with_custom_validator(validator, format, data)
end

defp validate_with_custom_validator({mod, fun}, format, data) do
case apply(mod, fun, [format, data]) do
defp do_validate(%Root{custom_format_validator: validator}, format, data) when is_function(validator) do
validate_with_custom_validator(validator, format, data)
end

defp validate_with_custom_validator(validator, format, data) do
result = case validator do
{mod, fun} -> apply(mod, fun, [format, data])
fun when is_function(fun, 2) -> fun.(format, data)
end
case result do
true -> []
false -> [%Error{error: %Error.Format{expected: format}}]
{:error, error} -> [%Error{error: error}]
Expand Down
25 changes: 25 additions & 0 deletions test/ex_json_schema/validator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,31 @@ defmodule ExJsonSchema.ValidatorTest do
)
end

test "configuring an anonymous function as custom format validator" do
anonymous_validation_fn = fn "myformat", data ->
data == "mydata"
end

schema =
Schema.resolve(
%{
"properties" => %{
"error" => %{"format" => "myformat"}
}
},
custom_format_validator: anonymous_validation_fn
)

assert :ok = validate(schema, %{"error" => "mydata"})

assert_validation_errors(
schema,
%{"error" => ""},
[{"Expected to be a valid myformat.", "#/error"}],
[%Error{error: %Error.Format{expected: "myformat"}, path: "#/error"}]
)
end

test "passing the formatter as an option" do
assert :ok = validate(%{"type" => "string"}, "foo", error_formatter: Error.StringFormatter)

Expand Down

0 comments on commit 72184a0

Please sign in to comment.