From 516548ff79f09a972acb79091a16776f043c8661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Biedrycki?= Date: Mon, 2 Dec 2013 15:37:14 +0100 Subject: [PATCH] Change a way to pass custom types definitions --- README.md | 20 ++++++- include/josser.hrl | 29 ---------- src/josser.app.src | 2 +- src/josser.erl | 23 +++++--- src/josser_custom_types.erl | 43 +------------- test/josser_metadata_SUITE.erl | 56 ++++++++----------- .../custom_type_boolean.json | 8 +++ .../custom_type_number.json | 6 ++ 8 files changed, 74 insertions(+), 113 deletions(-) delete mode 100644 include/josser.hrl create mode 100644 test/josser_metadata_SUITE_data/custom_type_boolean.json create mode 100644 test/josser_metadata_SUITE_data/custom_type_number.json diff --git a/README.md b/README.md index 7ad5db9..bd55f80 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/include/josser.hrl b/include/josser.hrl deleted file mode 100644 index 188e08e..0000000 --- a/include/josser.hrl +++ /dev/null @@ -1,29 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author Ɓukasz Biedrycki -%%% @doc -%%% JoSSER - Json Schema Generator -%%% @end -%%%------------------------------------------------------------------- - --type common_attrs(T, A) :: {type, T} - | {description, binary()} - | {required, boolean()} - | {enum, list(A)}. --type numeric_attrs(A) :: {minimum, A} - | {maximum, A} - | {exclusive_maximum, A} - | {exclusive_minimum, A}. --type custom_integer() :: [common_attrs(integer, integer()) - | numeric_attrs(integer())]. --type custom_number() :: [common_attrs(number, number()) - | numeric_attrs(number())]. --type custom_string() :: [common_attrs(string, binary()) - | {min_length, integer()} - | {max_length, integer()} - | {pattern, binary()}]. --type custom_boolean() :: [common_attrs(boolean, boolean())]. - --type custom_type_values() :: custom_integer() - | custom_number() - | custom_string() - | custom_boolean(). diff --git a/src/josser.app.src b/src/josser.app.src index ad7322e..e559b6d 100644 --- a/src/josser.app.src +++ b/src/josser.app.src @@ -1,6 +1,6 @@ { application, josser , [ {description, "josser - json schema generator"} - , {vsn, "0.1.0"} + , {vsn, "0.2.0"} , {modules, []} , {registered, []} , {applications, [ kernel diff --git a/src/josser.erl b/src/josser.erl index 5c84b8d..9db91a3 100644 --- a/src/josser.erl +++ b/src/josser.erl @@ -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]). @@ -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]). diff --git a/src/josser_custom_types.erl b/src/josser_custom_types.erl index c75f9cd..77cfcbb 100644 --- a/src/josser_custom_types.erl +++ b/src/josser_custom_types.erl @@ -9,8 +9,6 @@ -export([validate/2]). --include("josser.hrl"). - %%%=================================================================== %%% API %%%=================================================================== @@ -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}}). diff --git a/test/josser_metadata_SUITE.erl b/test/josser_metadata_SUITE.erl index c1657c2..9c4b09c 100644 --- a/test/josser_metadata_SUITE.erl +++ b/test/josser_metadata_SUITE.erl @@ -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#">>}). @@ -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) -> @@ -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">>}, @@ -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. @@ -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. @@ -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. @@ -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. diff --git a/test/josser_metadata_SUITE_data/custom_type_boolean.json b/test/josser_metadata_SUITE_data/custom_type_boolean.json new file mode 100644 index 0000000..bbecd50 --- /dev/null +++ b/test/josser_metadata_SUITE_data/custom_type_boolean.json @@ -0,0 +1,8 @@ +{ + "custom_type1": { + "type": "boolean", + "enum": [true], + "required": true, + "description": "desc" + } +} diff --git a/test/josser_metadata_SUITE_data/custom_type_number.json b/test/josser_metadata_SUITE_data/custom_type_number.json new file mode 100644 index 0000000..7e6f6d5 --- /dev/null +++ b/test/josser_metadata_SUITE_data/custom_type_number.json @@ -0,0 +1,6 @@ +{ + "custom_type1": { + "type": "number" + } +} +