Skip to content

Introduces Nullable validator #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/ex_json_schema/validator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ defmodule ExJsonSchema.Validator do

def do_validation_errors(root = %Root{}, schema = %{}, data, path) do
schema
# TODO
# |> Map.put_new("nullable", false)
|> Enum.flat_map(fn {propertyName, _} = property ->
case validator_for(propertyName) do
nil -> []
Expand Down Expand Up @@ -156,6 +158,7 @@ defmodule ExJsonSchema.Validator do
defp validator_for("$ref"), do: ExJsonSchema.Validator.Ref
defp validator_for("required"), do: ExJsonSchema.Validator.Required
defp validator_for("type"), do: ExJsonSchema.Validator.Type
defp validator_for("nullable"), do: ExJsonSchema.Validator.Nullable
defp validator_for("uniqueItems"), do: ExJsonSchema.Validator.UniqueItems
defp validator_for(_), do: nil
end
4 changes: 4 additions & 0 deletions lib/ex_json_schema/validator/error.ex
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ defmodule ExJsonSchema.Validator.Error do
defstruct([:missing])
end

defmodule Nullable do
defstruct([:allowed])
end

defmodule Type do
defstruct([:expected, :actual])
end
Expand Down
6 changes: 6 additions & 0 deletions lib/ex_json_schema/validator/error/string_formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ defmodule ExJsonSchema.Validator.Error.StringFormatter do
end
end

defimpl String.Chars, for: Error.Nullable do
def to_string(%Error.Nullable{allowed: false}) do
"Nullable value is not allowed."
end
end

defimpl String.Chars, for: Error.Type do
def to_string(%Error.Type{expected: expected, actual: actual}) do
"Type mismatch. Expected #{type_names(expected)} but got #{type_names(actual)}."
Expand Down
35 changes: 35 additions & 0 deletions lib/ex_json_schema/validator/nullable.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule ExJsonSchema.Validator.Nullable do
@moduledoc """
`ExJsonSchema.Validator` implementation for `"nullable"` attributes.

See:
https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.2
https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.25
https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
"""

alias ExJsonSchema.Validator.Error

@behaviour ExJsonSchema.Validator

@impl ExJsonSchema.Validator
def validate(_, _, {"nullable", nullable}, data, _) do
do_validate(nullable, data)
end

def validate(_, _, _, data, _) do
# by default nullable is not allowed
nullable = false
do_validate(nullable, data)
end

defp do_validate(nullable, data) do
if !nil_allowed?(nullable) && is_nil(data) do
[%Error{error: %Error.Nullable{allowed: false}}]
else
[]
end
end

defp nil_allowed?(nullable), do: nullable == true
end
1 change: 1 addition & 0 deletions lib/ex_json_schema/validator/type.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule ExJsonSchema.Validator.Type do
end
end

defp valid?(_, _, nil), do: true
defp valid?(_, "number", data), do: is_number(data)
defp valid?(_, "array", data), do: is_list(data)
defp valid?(_, "object", data), do: is_map(data)
Expand Down
13 changes: 13 additions & 0 deletions test/ex_json_schema/validator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,19 @@ defmodule ExJsonSchema.ValidatorTest do
validate(%{"type" => "string"}, 666, error_formatter: Error.StringFormatter)
end

test "allows attibute to have value nil if nullable is not specified" do
assert :ok = validate(%{"type" => "string"}, nil, error_formatter: Error.StringFormatter)
end

test "allows attibute to have value nil if nullable is allowed" do
assert :ok = validate(%{"type" => "string", "nullable" => true}, nil, error_formatter: Error.StringFormatter)
end

test "does not allowe nil values" do
assert {:error, [{"Nullable value is not allowed.", "#"}]} =
validate(%{"type" => "string", "nullable" => false}, nil, error_formatter: Error.StringFormatter)
end

test "using the string formatter by default" do
assert {:error, [{"Type mismatch. Expected String but got Integer.", "#"}]} = validate(%{"type" => "string"}, 666)
end
Expand Down