Skip to content
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

2600hz changes #42

Closed
wants to merge 16 commits into from
6 changes: 3 additions & 3 deletions src/jesse_error.erl
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@
%% throws an exeption, otherwise adds a new element to the list and returs it.
-spec default_error_handler( Error :: error_reason()
, ErrorList :: [error_reason()]
, AllowedErrors :: non_neg_integer()
, AllowedErrors :: non_neg_integer() | 'infinity'
) -> [error_reason()] | no_return().
default_error_handler(Error, ErrorList, AllowedErrors) ->
case AllowedErrors > length(ErrorList) orelse AllowedErrors =:= 'infinity' of
true -> [Error | ErrorList];
false -> throw([Error | ErrorList])
true -> ErrorList ++ [Error];
false -> throw(ErrorList ++ [Error])
end.

%% @doc Generates a new data error and returns the updated state.
Expand Down
10 changes: 10 additions & 0 deletions src/jesse_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
-export([ empty_if_not_found/1
, is_array/1
, is_json_object/1
, is_json_object_empty/1
, is_null/1
]).

Expand Down Expand Up @@ -67,3 +68,12 @@ is_json_object(_) -> false.
-spec is_null(Value :: any()) -> boolean().
is_null(null) -> true;
is_null(_Value) -> false.

%% @doc check if json object is_empty.
-spec is_json_object_empty(Value :: any()) -> boolean().
is_json_object_empty({struct, Value}) when is_list(Value) andalso Value =:= [] -> true;
is_json_object_empty({Value}) when is_list(Value) andalso Value =:= [] -> true;
%% handle `jsx' empty objects
is_json_object_empty([{}]) -> true;
?IF_MAPS(is_json_object_empty(Map) when erlang:is_map(Map) -> maps:size(Map) =:= 0;)
is_json_object_empty(_) -> false.
5 changes: 3 additions & 2 deletions src/jesse_schema_validator.erl
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@
, Options :: [{Key :: atom(), Data :: any()}]
) -> {ok, jesse:json_term()}
| no_return().
validate(JsonSchema, Value, Options) ->
validate(JsonSchema, Value, Options0) ->
Options = [{with_value, Value} | proplists:delete(with_value, Options0)],
State = jesse_state:new(JsonSchema, Options),
NewState = validate_with_state(JsonSchema, Value, State),
{result(NewState), Value}.
{result(NewState), jesse_state:get_current_value(NewState)}.

%% @doc Validates json `Data' against `JsonSchema' with `State'.
%% If the given json is valid, then the latest state is returned to the caller,
Expand Down
1 change: 1 addition & 0 deletions src/jesse_schema_validator.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
-define(MULTIPLEOF, <<"multipleOf">>).
-define(MAXPROPERTIES, <<"maxProperties">>).
-define(MINPROPERTIES, <<"minProperties">>).
-define(DEFAULT, <<"default">>).

%% Constant definitions for Json types
-define(ANY, <<"any">>).
Expand Down
66 changes: 63 additions & 3 deletions src/jesse_state.erl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
%% API
-export([ add_to_path/2
, get_allowed_errors/1
, get_extra_validator/1
, get_current_value/1
, get_current_path/1
, get_current_schema/1
, get_current_schema_id/1
Expand All @@ -36,25 +38,37 @@
, 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
]).

-type option() :: {Key :: atom(), Data :: any()}.
-type options() :: [option()].

-export_type([ state/0
, option/0
, options/0
]).

%% Includes
-include("jesse_schema_validator.hrl").

-type extra_validator() :: fun((jesse:json_term(), state()) -> state()) | undefined.
-type setter_fun() :: fun((jesse:json_path(), jesse:json_term(), jesse:json_term()) -> jesse:json_term()) | undefined.

%% Internal datastructures
-record( state
, { root_schema :: jesse:json_term()
, current_schema :: jesse:json_term()
, current_path :: [binary() | non_neg_integer()]
%% current path in reversed order
, current_value :: jesse:json_term()
, allowed_errors :: non_neg_integer() | 'infinity'
, error_list :: list()
, error_handler :: fun(( jesse_error:error_reason()
Expand All @@ -68,7 +82,10 @@
jesse:json_term() |
?not_found
)
, extra_validator :: extra_validator()
, setter_fun :: setter_fun()
, id :: http_uri:uri() | 'undefined'
, validator_options :: options()
}
).

Expand All @@ -83,7 +100,7 @@ add_to_path(State, Property) ->
State#state{current_path = [Property | CurrentPath]}.

%% @doc Getter for `allowed_errors'.
-spec get_allowed_errors(State :: state()) -> non_neg_integer().
-spec get_allowed_errors(State :: state()) -> non_neg_integer() | 'infinity'.
get_allowed_errors(#state{allowed_errors = AllowedErrors}) ->
AllowedErrors.

Expand Down Expand Up @@ -125,7 +142,7 @@ get_error_list(#state{error_list = ErrorList}) ->

%% @doc Returns newly created state.
-spec new( JsonSchema :: jesse:json_term()
, Options :: [{Key :: atom(), Data :: any()}]
, Options :: options()
) -> state().
new(JsonSchema, Options) ->
ErrorHandler = proplists:get_value( error_handler
Expand All @@ -148,13 +165,31 @@ new(JsonSchema, Options) ->
, Options
, ?default_schema_loader_fun
),
ExtraValidator = proplists:get_value( extra_validator
, Options
),
SetterFun = proplists:get_value( setter_fun
, Options
),
Value = proplists:get_value( with_value
, Options
),
ValidatorOptions = proplists:get_value( validator_options
, Options
, []
),

NewState = #state{ root_schema = JsonSchema
, current_path = []
, allowed_errors = AllowedErrors
, error_list = []
, error_handler = ErrorHandler
, default_schema_ver = DefaultSchemaVer
, schema_loader_fun = LoaderFun
, extra_validator = ExtraValidator
, setter_fun = SetterFun
, current_value = Value
, validator_options = ValidatorOptions
},
set_current_schema(NewState, JsonSchema).

Expand All @@ -165,7 +200,7 @@ remove_last_from_path(State = #state{current_path = [_Property | Path]}) ->

%% @doc Getter for `allowed_errors'.
-spec set_allowed_errors( State :: state()
, AllowedErrors :: non_neg_integer()
, AllowedErrors :: non_neg_integer() | 'infinity'
) -> state().
set_allowed_errors(#state{} = State, AllowedErrors) ->
State#state{allowed_errors = AllowedErrors}.
Expand Down Expand Up @@ -385,3 +420,28 @@ load_schema(#state{schema_loader_fun = LoaderFun}, SchemaURI) ->
%% io:format("load_schema: ~p\n", [{_C, _E, erlang:get_stacktrace()}]),
?not_found
end.

%% @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
}=State, Path, NewValue) ->
State#state{current_value = Setter(Path, NewValue, Value)}.

get_extra_validator(#state{extra_validator=Fun}) -> Fun.

-spec validator_options(State :: state()) -> 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).
Loading