|
31 | 31 | -include("jesse_schema_validator.hrl").
|
32 | 32 |
|
33 | 33 | -type schema_error() :: ?wrong_type_dependency
|
| 34 | + | ?schema_invalid |
34 | 35 | | ?wrong_type_items.
|
35 | 36 |
|
36 | 37 | -type schema_error_type() :: schema_error()
|
@@ -348,20 +349,19 @@ check_properties(Value, Properties, State) ->
|
348 | 349 | = lists:foldl( fun({PropertyName, PropertySchema}, CurrentState) ->
|
349 | 350 | case get_value(PropertyName, Value) of
|
350 | 351 | ?not_found ->
|
351 |
| -%% @doc 5.7. required |
352 |
| -%% |
353 |
| -%% This attribute indicates if the instance must have a value, and not |
354 |
| -%% be undefined. This is false by default, making the instance |
355 |
| -%% optional. |
356 |
| -%% @end |
357 |
| - case get_value(?REQUIRED, PropertySchema) of |
358 |
| - true -> |
359 |
| - handle_data_invalid( {?missing_required_property |
360 |
| - , PropertyName} |
361 |
| - , Value |
362 |
| - , CurrentState); |
363 |
| - _ -> |
364 |
| - CurrentState |
| 352 | + case get_value(?DEFAULT, PropertySchema) of |
| 353 | + ?not_found -> |
| 354 | + check_required( PropertySchema |
| 355 | + , PropertyName |
| 356 | + , Value |
| 357 | + , CurrentState |
| 358 | + ); |
| 359 | + Default -> |
| 360 | + check_default( PropertyName |
| 361 | + , PropertySchema |
| 362 | + , Default |
| 363 | + , CurrentState |
| 364 | + ) |
365 | 365 | end;
|
366 | 366 | Property ->
|
367 | 367 | NewState = set_current_schema( CurrentState
|
@@ -583,6 +583,24 @@ check_items_fun(Tuples, State) ->
|
583 | 583 | ),
|
584 | 584 | set_current_schema(TmpState, get_current_schema(State)).
|
585 | 585 |
|
| 586 | + |
| 587 | +%% @doc 5.7. required |
| 588 | +%% |
| 589 | +%% This attribute indicates if the instance must have a value, and not |
| 590 | +%% be undefined. This is false by default, making the instance |
| 591 | +%% optional. |
| 592 | +%% @private |
| 593 | +check_required(PropertySchema, PropertyName, Value, CurrentState) -> |
| 594 | + case get_value(?REQUIRED, PropertySchema) of |
| 595 | + true -> |
| 596 | + handle_data_invalid( {?missing_required_property |
| 597 | + , PropertyName} |
| 598 | + , Value |
| 599 | + , CurrentState); |
| 600 | + _ -> |
| 601 | + CurrentState |
| 602 | + end. |
| 603 | + |
586 | 604 | %% @doc 5.8. dependencies
|
587 | 605 | %%
|
588 | 606 | %% This attribute is an object that defines the requirements of a
|
@@ -904,7 +922,8 @@ validate_ref(Value, Reference, State) ->
|
904 | 922 | {error, NewState} ->
|
905 | 923 | undo_resolve_ref(NewState, State);
|
906 | 924 | {ok, NewState, Schema} ->
|
907 |
| - ResultState = jesse_schema_validator:validate_with_state(Schema, Value, NewState), |
| 925 | + ResultState = |
| 926 | + jesse_schema_validator:validate_with_state(Schema, Value, NewState), |
908 | 927 | undo_resolve_ref(ResultState, State)
|
909 | 928 | end.
|
910 | 929 |
|
@@ -992,7 +1011,11 @@ compare_properties(Value1, Value2) ->
|
992 | 1011 | %% Wrappers
|
993 | 1012 | %% @private
|
994 | 1013 | get_value(Key, Schema) ->
|
995 |
| - jesse_json_path:value(Key, Schema, ?not_found). |
| 1014 | + get_value(Key, Schema, ?not_found). |
| 1015 | + |
| 1016 | +%% @private |
| 1017 | +get_value(Key, Schema, Default) -> |
| 1018 | + jesse_json_path:value(Key, Schema, Default). |
996 | 1019 |
|
997 | 1020 | %% @private
|
998 | 1021 | unwrap(Value) ->
|
@@ -1041,3 +1064,80 @@ maybe_external_check_value(Value, State) ->
|
1041 | 1064 | Fun ->
|
1042 | 1065 | Fun(Value, State)
|
1043 | 1066 | end.
|
| 1067 | + |
| 1068 | +%% @private |
| 1069 | +validator_option(Option, State, Default) -> |
| 1070 | + jesse_state:validator_option(Option, State, Default). |
| 1071 | + |
| 1072 | +%% @private |
| 1073 | +set_value(PropertyName, Value, State) -> |
| 1074 | + Path = lists:reverse([PropertyName] ++ jesse_state:get_current_path(State)), |
| 1075 | + jesse_state:set_value(State, Path, Value). |
| 1076 | + |
| 1077 | +%% @private |
| 1078 | +check_default_for_type(Default, State) -> |
| 1079 | + validator_option('use_defaults', State, false) |
| 1080 | + andalso (not jesse_lib:is_json_object(Default) |
| 1081 | + orelse validator_option( 'apply_defaults_to_empty_objects' |
| 1082 | + , State |
| 1083 | + , false |
| 1084 | + ) |
| 1085 | + orelse not jesse_lib:is_json_object_empty(Default)). |
| 1086 | + |
| 1087 | +%% @private |
| 1088 | +check_default(PropertyName, PropertySchema, Default, State) -> |
| 1089 | + Type = get_value(?TYPE, PropertySchema, ?not_found), |
| 1090 | + case is_valid_default(Type, Default, State) of |
| 1091 | + true -> |
| 1092 | + set_default(PropertyName, PropertySchema, Default, State); |
| 1093 | + false -> |
| 1094 | + State |
| 1095 | + end. |
| 1096 | + |
| 1097 | +%% @private |
| 1098 | +is_valid_default(?not_found, _Default, _State) -> |
| 1099 | + false; |
| 1100 | +is_valid_default(Type, Default, State) |
| 1101 | + when is_binary(Type) -> |
| 1102 | + check_default_for_type(Default, State) |
| 1103 | + andalso is_type_valid(Default, Type, State); |
| 1104 | +is_valid_default(Types, Default, State) |
| 1105 | + when is_list(Types) -> |
| 1106 | + check_default_for_type(Default, State) |
| 1107 | + andalso lists:any( fun(Type) -> |
| 1108 | + is_type_valid(Default, Type, State) |
| 1109 | + end |
| 1110 | + , Types |
| 1111 | + ); |
| 1112 | +is_valid_default(_, _Default, _State) -> false. |
| 1113 | + |
| 1114 | +%% @private |
| 1115 | +set_default(PropertyName, PropertySchema, Default, State) -> |
| 1116 | + State1 = set_value(PropertyName, Default, State), |
| 1117 | + State2 = add_to_path(State1, PropertyName), |
| 1118 | + case validate_schema(Default, PropertySchema, State2) of |
| 1119 | + {true, State4} -> |
| 1120 | + jesse_state:remove_last_from_path(State4); |
| 1121 | + _ -> |
| 1122 | + State |
| 1123 | + end. |
| 1124 | + |
| 1125 | +%% @doc Validate a value against a schema in a given state. |
| 1126 | +%% Used by all combinators to run validation on a schema. |
| 1127 | +%% @private |
| 1128 | +validate_schema(Value, Schema, State0) -> |
| 1129 | + try |
| 1130 | + case jesse_lib:is_json_object(Schema) of |
| 1131 | + true -> |
| 1132 | + State1 = set_current_schema(State0, Schema), |
| 1133 | + State2 = jesse_schema_validator:validate_with_state( Schema |
| 1134 | + , Value |
| 1135 | + , State1 |
| 1136 | + ), |
| 1137 | + {true, State2}; |
| 1138 | + false -> |
| 1139 | + handle_schema_invalid(?schema_invalid, State0) |
| 1140 | + end |
| 1141 | + catch |
| 1142 | + throw:Errors -> {false, Errors} |
| 1143 | + end. |
0 commit comments