|
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,21 +349,14 @@ 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 |
365 | | - end; |
| 352 | + case get_value(?DEFAULT, PropertySchema) of |
| 353 | + ?not_found -> check_required( PropertySchema |
| 354 | + , PropertyName |
| 355 | + , Value |
| 356 | + , CurrentState |
| 357 | + ); |
| 358 | + Default -> check_default(PropertyName, PropertySchema, Default, CurrentState) |
| 359 | + end; |
366 | 360 | Property -> |
367 | 361 | NewState = set_current_schema( CurrentState |
368 | 362 | , PropertySchema |
@@ -583,6 +577,24 @@ check_items_fun(Tuples, State) -> |
583 | 577 | ), |
584 | 578 | set_current_schema(TmpState, get_current_schema(State)). |
585 | 579 |
|
| 580 | + |
| 581 | +%% @doc 5.7. required |
| 582 | +%% |
| 583 | +%% This attribute indicates if the instance must have a value, and not |
| 584 | +%% be undefined. This is false by default, making the instance |
| 585 | +%% optional. |
| 586 | +%% @private |
| 587 | +check_required(PropertySchema, PropertyName, Value, CurrentState) -> |
| 588 | + case get_value(?REQUIRED, PropertySchema) of |
| 589 | + true -> |
| 590 | + handle_data_invalid( {?missing_required_property |
| 591 | + , PropertyName} |
| 592 | + , Value |
| 593 | + , CurrentState); |
| 594 | + _ -> |
| 595 | + CurrentState |
| 596 | + end. |
| 597 | + |
586 | 598 | %% @doc 5.8. dependencies |
587 | 599 | %% |
588 | 600 | %% This attribute is an object that defines the requirements of a |
@@ -980,7 +992,11 @@ compare_properties(Value1, Value2) -> |
980 | 992 | %% Wrappers |
981 | 993 | %% @private |
982 | 994 | get_value(Key, Schema) -> |
983 | | - jesse_json_path:value(Key, Schema, ?not_found). |
| 995 | + get_value(Key, Schema, ?not_found). |
| 996 | + |
| 997 | +%% @private |
| 998 | +get_value(Key, Schema, Default) -> |
| 999 | + jesse_json_path:value(Key, Schema, Default). |
984 | 1000 |
|
985 | 1001 | %% @private |
986 | 1002 | unwrap(Value) -> |
@@ -1027,3 +1043,54 @@ check_external_validation(Value, State) -> |
1027 | 1043 | undefined -> State; |
1028 | 1044 | Fun -> Fun(Value, State) |
1029 | 1045 | end. |
| 1046 | + |
| 1047 | +%% @private |
| 1048 | +set_value(PropertyName, Value, State) -> |
| 1049 | + Path = lists:reverse([PropertyName] ++ jesse_state:get_current_path(State)), |
| 1050 | + jesse_state:set_value(State, Path, Value). |
| 1051 | + |
| 1052 | +-define(types_for_defaults, [ ?STRING |
| 1053 | + , ?NUMBER |
| 1054 | + , ?INTEGER |
| 1055 | + , ?BOOLEAN |
| 1056 | + , ?OBJECT |
| 1057 | + ]). |
| 1058 | + |
| 1059 | +%% @private |
| 1060 | +check_default(PropertyName, PropertySchema, Default, State) -> |
| 1061 | + Type = get_value(?TYPE, PropertySchema, ?not_found), |
| 1062 | + case Type =/= ?not_found |
| 1063 | + andalso lists:member(Type, ?types_for_defaults) |
| 1064 | + andalso is_type_valid(Default, Type, State) of |
| 1065 | + false -> State; |
| 1066 | + true -> set_default(PropertyName, PropertySchema, Default, State) |
| 1067 | + end. |
| 1068 | + |
| 1069 | +%% @private |
| 1070 | +set_default(PropertyName, PropertySchema, Default, State) -> |
| 1071 | + State1 = set_value(PropertyName, Default, State), |
| 1072 | + Schema = jesse_state:get_current_schema(State1), |
| 1073 | + case Schema =/= PropertySchema andalso validate_schema(Default, PropertySchema, State1) of |
| 1074 | + {true, State4} -> State4; |
| 1075 | + _ -> State |
| 1076 | + end. |
| 1077 | + |
| 1078 | +%% @doc Validate a value against a schema in a given state. |
| 1079 | +%% Used by all combinators to run validation on a schema. |
| 1080 | +%% @private |
| 1081 | +validate_schema(Value, Schema, State0) -> |
| 1082 | + try |
| 1083 | + case jesse_lib:is_json_object(Schema) of |
| 1084 | + true -> |
| 1085 | + State1 = set_current_schema(State0, Schema), |
| 1086 | + State2 = jesse_schema_validator:validate_with_state( Schema |
| 1087 | + , Value |
| 1088 | + , State1 |
| 1089 | + ), |
| 1090 | + {true, State2}; |
| 1091 | + false -> |
| 1092 | + handle_schema_invalid(?schema_invalid, State0) |
| 1093 | + end |
| 1094 | + catch |
| 1095 | + throw:Errors -> {false, Errors} |
| 1096 | + end. |
0 commit comments