Skip to content

Commit

Permalink
Change a way to pass custom types definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
loucash committed Dec 2, 2013
1 parent 1bfee82 commit 516548f
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 113 deletions.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,31 @@ Examples

```erlang
1> josser:make_custom_schema([{<<"key">>, <<"{\"type\": \"custom_type\"}">>}],
[{<<"custom_type">>, [{type, integer}, {maximum, 10}]}]).
{json_term, [{<<"custom_type">>, [{<<"type">>, <<"integer">>}, {<<"maximum">>, 10}]}]}).
{ok,[{<<"$schema">>,<<"http://json-schema.org/schema#">>},
{<<"properties">>,
[{<<"key">>,
[{<<"type">>,<<"integer">>},{<<"maximum">>,10}]}]}]}
```

`make_custom_schema` get `CustomTypes` argument as:

* `{file, "path/to/file.json"}`

* or:

```
{json_text, <<"{\"custom_type\": {\"type\": \"string\", \"description\": \"description\"},
\"other_custom_type\": {...}}">>}
```
* or:
```
{json_term, [{<<"custom_type">>, [{<<"type">>, <<"string">>}]}]}
```
Contributing
------------
If you see something missing or incorrect, do not hesitate to create an issue
Expand Down
29 changes: 0 additions & 29 deletions include/josser.hrl

This file was deleted.

2 changes: 1 addition & 1 deletion src/josser.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{ application, josser
, [ {description, "josser - json schema generator"}
, {vsn, "0.1.0"}
, {vsn, "0.2.0"}
, {modules, []}
, {registered, []}
, {applications, [ kernel
Expand Down
23 changes: 16 additions & 7 deletions src/josser.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@
make_custom_schema/2,
make_custom_schema/3]).

-include("josser.hrl").

-type options() :: {additional_properties, boolean()}
| {encode_json, boolean()}
| {value_as_metadata, boolean()}.
-type option_list() :: [options()].
-type josser_errors() :: {missing_type, binary()}
| {invalid_custom_type_attr, binary()}.
-type josser_errors() :: {missing_type, binary()}.
-type josser_result() :: {ok, jsx:json_text()}
| {ok, jsx:json_term()}
| {error, josser_errors()}.
-type custom_types() :: [{binary(), custom_type_values()}].
-type custom_types() :: {file, string()}
| {json_term, jsx:json_term()}
| {json_text, jsx:json_text()}.

-export_type([custom_types/0]).

Expand All @@ -49,12 +48,22 @@ make_schema(JSON, Options) ->
generate(JSON, [], Options).

-spec make_custom_schema(jsx:json_term(), custom_types()) -> josser_result().
make_custom_schema(JSON, CustomTypes) ->
make_custom_schema(JSON, {file, CustomTypesFilePath}) ->
{ok, Json} = file:read_file(CustomTypesFilePath),
make_custom_schema(JSON, {json_text, Json});
make_custom_schema(JSON, {json_text, Json}) ->
make_custom_schema(JSON, {json_term, jsx:decode(Json)});
make_custom_schema(JSON, {json_term, CustomTypes}) ->
generate(JSON, CustomTypes, [{value_as_metadata, true}]).

-spec make_custom_schema(jsx:json_term(), custom_types(),
option_list()) -> josser_result().
make_custom_schema(JSON, CustomTypes, Options) ->
make_custom_schema(JSON, {file, CustomTypesFilePath}, Options) ->
{ok, Json} = file:read_file(CustomTypesFilePath),
make_custom_schema(JSON, {json_text, Json}, Options);
make_custom_schema(JSON, {json_text, Json}, Options) ->
make_custom_schema(JSON, {json_term, jsx:decode(Json)}, Options);
make_custom_schema(JSON, {json_term, CustomTypes}, Options) ->
generate(JSON, CustomTypes, [{value_as_metadata, true} | Options]).


Expand Down
43 changes: 1 addition & 42 deletions src/josser_custom_types.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

-export([validate/2]).

-include("josser.hrl").

%%%===================================================================
%%% API
%%%===================================================================
Expand Down Expand Up @@ -43,44 +41,5 @@ validate_simple_type(_Other) -> false.
validate_custom_type(Type, CustomTypes) ->
case proplists:get_value(Type, CustomTypes) of
undefined -> erlang:throw({error, {missing_type, Type}});
CustomType -> {ok, render_custom_type(CustomType, [])}
CustomType -> {ok, CustomType}
end.

-spec render_custom_type(josser:custom_types(), list()) ->
[{binary(), binary()
| boolean()
| number()
| list(binary() | boolean() | number())}]
| no_return().
render_custom_type([], Acc) ->
lists:reverse(Acc);
render_custom_type([{type, boolean} | Tail], Acc) ->
render_custom_type(Tail, [{<<"type">>, <<"boolean">>} | Acc]);
render_custom_type([{type, string} | Tail], Acc) ->
render_custom_type(Tail, [{<<"type">>, <<"string">>} | Acc]);
render_custom_type([{type, number} | Tail], Acc) ->
render_custom_type(Tail, [{<<"type">>, <<"number">>} | Acc]);
render_custom_type([{type, integer} | Tail], Acc) ->
render_custom_type(Tail, [{<<"type">>, <<"integer">>} | Acc]);
render_custom_type([{description, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"description">>, Value} | Acc]);
render_custom_type([{required, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"required">>, Value} | Acc]);
render_custom_type([{enum, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"enum">>, Value} | Acc]);
render_custom_type([{minimum, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"minimum">>, Value} | Acc]);
render_custom_type([{maximum, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"maximum">>, Value} | Acc]);
render_custom_type([{exclusive_maximum, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"exclusiveMaximum">>, Value} | Acc]);
render_custom_type([{exclusive_minimum, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"exclusiveMinimum">>, Value} | Acc]);
render_custom_type([{min_length, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"minLength">>, Value} | Acc]);
render_custom_type([{max_length, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"maxLength">>, Value} | Acc]);
render_custom_type([{pattern, Value} | Tail], Acc) ->
render_custom_type(Tail, [{<<"pattern">>, Value} | Acc]);
render_custom_type([Other | _Tail], _Acc) ->
erlang:throw({error, {invalid_custom_type_attr, Other}}).
56 changes: 23 additions & 33 deletions test/josser_metadata_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
-compile(export_all).

-include_lib("common_test/include/ct.hrl").
-include("josser.hrl").

-define(DEFAULT_SCHEMA, {<<"$schema">>, <<"http://json-schema.org/schema#">>}).

Expand All @@ -14,8 +13,7 @@ all() ->
t_custom_type_integer,
t_custom_type_string,
t_custom_type_number,
t_undefined_custom_type,
t_invalid_custom_type_attr
t_undefined_custom_type
].

t_simple_json_types(_Config) ->
Expand Down Expand Up @@ -94,7 +92,10 @@ t_simple_json_types(_Config) ->
TestData),
ok.

t_custom_type_boolean(_Config) ->
t_custom_type_boolean(Config) ->
CustomTypesFile = filename:join(
?config(data_dir, Config),
"custom_type_boolean.json"),
Json = [{<<"key">>, <<"{\"type\": \"custom_type1\"}">>}],
JsonSchema = [?DEFAULT_SCHEMA,
{<<"type">>, <<"object">>},
Expand All @@ -105,11 +106,7 @@ t_custom_type_boolean(_Config) ->
{<<"description">>, <<"desc">>}]}]}],
{ok, JS} = josser:make_custom_schema(
Json,
[{<<"custom_type1">>,
[{type, boolean},
{enum, [true]},
{required, true},
{description, <<"desc">>}]}]),
{file, CustomTypesFile}),
true = jsx:is_term(JS),
JsonSchema = JS,
ok.
Expand All @@ -126,25 +123,25 @@ t_custom_type_integer(_Config) ->
{<<"exclusiveMaximum">>, false}]}]}],
{ok, JS} = josser:make_custom_schema(
Json,
[{<<"custom_type1">>,
[{type, integer},
{minimum, 0},
{maximum, 10},
{exclusive_minimum, true},
{exclusive_maximum, false}]}]),
{json_term, [{<<"custom_type1">>,
[{<<"type">>, <<"integer">>},
{<<"minimum">>, 0},
{<<"maximum">>, 10},
{<<"exclusiveMinimum">>, true},
{<<"exclusiveMaximum">>, false}]}]}),
true = jsx:is_term(JS),
JsonSchema = JS,
ok.

t_custom_type_number(_Config) ->
t_custom_type_number(Config) ->
CustomTypesFile = filename:join(
?config(data_dir, Config),
"custom_type_number.json"),
Json = [{<<"key">>, <<"{\"type\": \"custom_type1\"}">>}],
JsonSchema = <<"{\"$schema\":\"http://json-schema.org/schema#\","
"\"type\":\"object\",\"properties\":{\"key\":{\"type\":\"number\"}}}">>,
{ok, JS} = josser:make_custom_schema(
Json,
[{<<"custom_type1">>,
[{type, number}]}],
[{encode_json, true}]),
Json, {file, CustomTypesFile}, [{encode_json, true}]),
true = jsx:is_json(JS),
JsonSchema = JS,
ok.
Expand All @@ -160,11 +157,11 @@ t_custom_type_string(_Config) ->
{<<"pattern">>, <<"pattern">>}]}]}],
{ok, JS} = josser:make_custom_schema(
Json,
[{<<"custom_type1">>,
[{type, string},
{min_length, 0},
{max_length, 10},
{pattern, <<"pattern">>}]}]),
{json_term, [{<<"custom_type1">>,
[{<<"type">>, <<"string">>},
{<<"minLength">>, 0},
{<<"maxLength">>, 10},
{<<"pattern">>, <<"pattern">>}]}]}),
true = jsx:is_term(JS),
JsonSchema = JS,
ok.
Expand All @@ -173,12 +170,5 @@ t_undefined_custom_type(_Config) ->
Json = [{<<"key">>, <<"{\"type\": \"custom_type1\"}">>}],
{error, {missing_type, _CType}} = josser:make_custom_schema(
Json,
[{<<"custom_type2">>, [{type, boolean}]}]),
ok.

t_invalid_custom_type_attr(_Config) ->
Json = [{<<"key">>, <<"{\"type\": \"custom_type1\"}">>}],
{error, {invalid_custom_type_attr, _CType}} = josser:make_custom_schema(
Json,
[{<<"custom_type1">>, [{type, boolean}, {wrong_attr, value}]}]),
{json_term, [{<<"custom_type2">>, [{<<"type">>, <<"boolean">>}]}]}),
ok.
8 changes: 8 additions & 0 deletions test/josser_metadata_SUITE_data/custom_type_boolean.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"custom_type1": {
"type": "boolean",
"enum": [true],
"required": true,
"description": "desc"
}
}
6 changes: 6 additions & 0 deletions test/josser_metadata_SUITE_data/custom_type_number.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"custom_type1": {
"type": "number"
}
}

0 comments on commit 516548f

Please sign in to comment.