-
Notifications
You must be signed in to change notification settings - Fork 63
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
default #52
base: master
Are you sure you want to change the base?
default #52
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
-export([ add_to_path/2 | ||
, get_allowed_errors/1 | ||
, get_external_validator/1 | ||
, get_current_value/1 | ||
, get_current_path/1 | ||
, get_current_schema/1 | ||
, get_current_schema_id/1 | ||
|
@@ -37,11 +38,14 @@ | |
, remove_last_from_path/1 | ||
, set_allowed_errors/2 | ||
, set_current_schema/2 | ||
, set_value/3 | ||
, set_error_list/2 | ||
, resolve_ref/2 | ||
, undo_resolve_ref/2 | ||
, canonical_path/2 | ||
, combine_id/2 | ||
, validator_options/1 | ||
, validator_option/2, validator_option/3 | ||
]). | ||
|
||
-export_type([ state/0 | ||
|
@@ -55,13 +59,16 @@ | |
, { allowed_errors :: jesse:allowed_errors() | ||
, current_path :: current_path() | ||
, current_schema :: jesse:schema() | ||
, current_value :: jesse:json_term() | ||
, default_schema_ver :: jesse:schema_ver() | ||
, error_handler :: jesse:error_handler() | ||
, error_list :: jesse:error_list() | ||
, external_validator :: jesse:external_validator() | ||
, id :: jesse:schema_id() | ||
, root_schema :: jesse:schema() | ||
, schema_loader_fun :: jesse:schema_loader_fun() | ||
, setter_fun :: jesse:setter_fun() | ||
, validator_options :: jesse:options() | ||
} | ||
). | ||
|
||
|
@@ -146,6 +153,16 @@ new(JsonSchema, Options) -> | |
, Options | ||
, ?default_schema_loader_fun | ||
), | ||
SetterFun = proplists:get_value( setter_fun | ||
, Options | ||
), | ||
Value = proplists:get_value( with_value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
|
||
, Options | ||
), | ||
ValidatorOptions = proplists:get_value( validator_options | ||
, Options | ||
, [] | ||
), | ||
NewState = #state{ root_schema = JsonSchema | ||
, current_path = [] | ||
, allowed_errors = AllowedErrors | ||
|
@@ -154,6 +171,9 @@ new(JsonSchema, Options) -> | |
, default_schema_ver = DefaultSchemaVer | ||
, schema_loader_fun = LoaderFun | ||
, external_validator = ExternalValidator | ||
, setter_fun = SetterFun | ||
, current_value = Value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
|
||
, validator_options = ValidatorOptions | ||
}, | ||
set_current_schema(NewState, JsonSchema). | ||
|
||
|
@@ -205,14 +225,22 @@ resolve_ref(State, Reference) -> | |
Path = jesse_json_path:parse(Pointer), | ||
case load_local_schema(State#state.root_schema, Path) of | ||
?not_found -> | ||
jesse_error:handle_schema_invalid({?schema_not_found, CanonicalReference}, State); | ||
jesse_error:handle_schema_invalid( { ?schema_not_found | ||
, CanonicalReference | ||
} | ||
, State | ||
); | ||
Schema -> | ||
set_current_schema(State, Schema) | ||
end; | ||
false -> | ||
case load_schema(State, BaseURI) of | ||
?not_found -> | ||
jesse_error:handle_schema_invalid({?schema_not_found, CanonicalReference}, State); | ||
jesse_error:handle_schema_invalid( { ?schema_not_found | ||
, CanonicalReference | ||
} | ||
, State | ||
); | ||
RemoteSchema -> | ||
SchemaVer = | ||
jesse_json_path:value(?SCHEMA, RemoteSchema, ?default_schema_ver), | ||
|
@@ -223,7 +251,11 @@ resolve_ref(State, Reference) -> | |
Path = jesse_json_path:parse(Pointer), | ||
case load_local_schema(RemoteSchema, Path) of | ||
?not_found -> | ||
jesse_error:handle_schema_invalid({?schema_not_found, CanonicalReference}, State); | ||
jesse_error:handle_schema_invalid( { ?schema_not_found | ||
, CanonicalReference | ||
} | ||
, State | ||
); | ||
Schema -> | ||
set_current_schema(NewState, Schema) | ||
end | ||
|
@@ -392,3 +424,32 @@ load_schema(#state{schema_loader_fun = LoaderFun}, SchemaURI) -> | |
%% @private | ||
get_external_validator(#state{external_validator = Fun}) -> | ||
Fun. | ||
|
||
%% @doc Getter for `current_value'. | ||
-spec get_current_value(State :: state()) -> jesse:json_term(). | ||
get_current_value(#state{current_value = Value}) -> | ||
Value. | ||
|
||
-spec set_value(State :: state(), jesse:path(), jesse:json_term()) -> state(). | ||
set_value(#state{setter_fun = undefined}=State, _Path, _Value) -> State; | ||
set_value(#state{current_value = undefined}=State, _Path, _Value) -> State; | ||
set_value( #state{ setter_fun = Setter | ||
, current_value = Value | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
|
||
} = State | ||
, Path | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
|
||
, NewValue | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Compiler:
|
||
) -> | ||
State#state{current_value = Setter(Path, NewValue, Value)}. | ||
|
||
-spec validator_options(State :: state()) -> jesse:options(). | ||
validator_options(#state{validator_options = Options}) -> | ||
Options. | ||
|
||
-spec validator_option(Option :: atom(), State :: state()) -> any(). | ||
validator_option(Option, #state{validator_options = Options}) -> | ||
proplists:get_value(Option, Options). | ||
|
||
-spec validator_option(Option :: atom(), State :: state(), Default :: any()) -> | ||
any(). | ||
validator_option(Option, #state{validator_options = Options}, Default) -> | ||
proplists:get_value(Option, Options, Default). |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
-include("jesse_schema_validator.hrl"). | ||
|
||
-type schema_error() :: ?wrong_type_dependency | ||
| ?schema_invalid | ||
| ?wrong_type_items. | ||
|
||
-type schema_error_type() :: schema_error() | ||
|
@@ -348,20 +349,19 @@ check_properties(Value, Properties, State) -> | |
= lists:foldl( fun({PropertyName, PropertySchema}, CurrentState) -> | ||
case get_value(PropertyName, Value) of | ||
?not_found -> | ||
%% @doc 5.7. required | ||
%% | ||
%% This attribute indicates if the instance must have a value, and not | ||
%% be undefined. This is false by default, making the instance | ||
%% optional. | ||
%% @end | ||
case get_value(?REQUIRED, PropertySchema) of | ||
true -> | ||
handle_data_invalid( {?missing_required_property | ||
, PropertyName} | ||
, Value | ||
, CurrentState); | ||
_ -> | ||
CurrentState | ||
case get_value(?DEFAULT, PropertySchema) of | ||
?not_found -> | ||
check_required( PropertySchema | ||
, PropertyName | ||
, Value | ||
, CurrentState | ||
); | ||
Default -> | ||
check_default( PropertyName | ||
, PropertySchema | ||
, Default | ||
, CurrentState | ||
) | ||
end; | ||
Property -> | ||
NewState = set_current_schema( CurrentState | ||
|
@@ -583,6 +583,24 @@ check_items_fun(Tuples, State) -> | |
), | ||
set_current_schema(TmpState, get_current_schema(State)). | ||
|
||
|
||
%% @doc 5.7. required | ||
%% | ||
%% This attribute indicates if the instance must have a value, and not | ||
%% be undefined. This is false by default, making the instance | ||
%% optional. | ||
%% @private | ||
check_required(PropertySchema, PropertyName, Value, CurrentState) -> | ||
case get_value(?REQUIRED, PropertySchema) of | ||
true -> | ||
handle_data_invalid( {?missing_required_property | ||
, PropertyName} | ||
, Value | ||
, CurrentState); | ||
_ -> | ||
CurrentState | ||
end. | ||
|
||
%% @doc 5.8. dependencies | ||
%% | ||
%% This attribute is an object that defines the requirements of a | ||
|
@@ -904,7 +922,8 @@ validate_ref(Value, Reference, State) -> | |
{error, NewState} -> | ||
undo_resolve_ref(NewState, State); | ||
{ok, NewState, Schema} -> | ||
ResultState = jesse_schema_validator:validate_with_state(Schema, Value, NewState), | ||
ResultState = | ||
jesse_schema_validator:validate_with_state(Schema, Value, NewState), | ||
undo_resolve_ref(ResultState, State) | ||
end. | ||
|
||
|
@@ -992,7 +1011,11 @@ compare_properties(Value1, Value2) -> | |
%% Wrappers | ||
%% @private | ||
get_value(Key, Schema) -> | ||
jesse_json_path:value(Key, Schema, ?not_found). | ||
get_value(Key, Schema, ?not_found). | ||
|
||
%% @private | ||
get_value(Key, Schema, Default) -> | ||
jesse_json_path:value(Key, Schema, Default). | ||
|
||
%% @private | ||
unwrap(Value) -> | ||
|
@@ -1041,3 +1064,80 @@ maybe_external_check_value(Value, State) -> | |
Fun -> | ||
Fun(Value, State) | ||
end. | ||
|
||
%% @private | ||
validator_option(Option, State, Default) -> | ||
jesse_state:validator_option(Option, State, Default). | ||
|
||
%% @private | ||
set_value(PropertyName, Value, State) -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to Xref:
|
||
Path = lists:reverse([PropertyName] ++ jesse_state:get_current_path(State)), | ||
jesse_state:set_value(State, Path, Value). | ||
|
||
%% @private | ||
check_default_for_type(Default, State) -> | ||
validator_option('use_defaults', State, false) | ||
andalso (not jesse_lib:is_json_object(Default) | ||
orelse validator_option( 'apply_defaults_to_empty_objects' | ||
, State | ||
, false | ||
) | ||
orelse not jesse_lib:is_json_object_empty(Default)). | ||
|
||
%% @private | ||
check_default(PropertyName, PropertySchema, Default, State) -> | ||
Type = get_value(?TYPE, PropertySchema, ?not_found), | ||
case is_valid_default(Type, Default, State) of | ||
true -> | ||
set_default(PropertyName, PropertySchema, Default, State); | ||
false -> | ||
State | ||
end. | ||
|
||
%% @private | ||
is_valid_default(?not_found, _Default, _State) -> | ||
false; | ||
is_valid_default(Type, Default, State) | ||
when is_binary(Type) -> | ||
check_default_for_type(Default, State) | ||
andalso is_type_valid(Default, Type, State); | ||
is_valid_default(Types, Default, State) | ||
when is_list(Types) -> | ||
check_default_for_type(Default, State) | ||
andalso lists:any( fun(Type) -> | ||
is_type_valid(Default, Type, State) | ||
end | ||
, Types | ||
); | ||
is_valid_default(_, _Default, _State) -> false. | ||
|
||
%% @private | ||
set_default(PropertyName, PropertySchema, Default, State) -> | ||
State1 = set_value(PropertyName, Default, State), | ||
State2 = add_to_path(State1, PropertyName), | ||
case validate_schema(Default, PropertySchema, State2) of | ||
{true, State4} -> | ||
jesse_state:remove_last_from_path(State4); | ||
_ -> | ||
State | ||
end. | ||
|
||
%% @doc Validate a value against a schema in a given state. | ||
%% Used by all combinators to run validation on a schema. | ||
%% @private | ||
validate_schema(Value, Schema, State0) -> | ||
try | ||
case jesse_lib:is_json_object(Schema) of | ||
true -> | ||
State1 = set_current_schema(State0, Schema), | ||
State2 = jesse_schema_validator:validate_with_state( Schema | ||
, Value | ||
, State1 | ||
), | ||
{true, State2}; | ||
false -> | ||
handle_schema_invalid(?schema_invalid, State0) | ||
end | ||
catch | ||
throw:Errors -> {false, Errors} | ||
end. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to Compiler: