diff --git a/include/jsx_common.hrl b/include/jsx_common.hrl index aa31871..4f4790c 100644 --- a/include/jsx_common.hrl +++ b/include/jsx_common.hrl @@ -28,4 +28,104 @@ ; X == utf32 ; X == {utf16, little} ; X == {utf32, little} -). \ No newline at end of file +). + + +-type jsx_opts() :: [jsx_opt()]. +-type jsx_opt() :: {comments, true | false} + | {escaped_unicode, ascii | codepoint | none} + | {multi_term, true | false} + | {encoding, auto + | utf8 + | utf16 + | {utf16, little} + | utf32 + | {utf32, little} + }. + + +%% events emitted by the parser and component types +-type unicode_codepoint() :: 0..16#10ffff. +-type unicode_string() :: [unicode_codepoint()]. + +-type jsx_event() :: start_object + | end_object + | start_array + | end_array + | end_json + | {key, unicode_string()} + | {string, unicode_string()} + | {integer, unicode_string()} + | {float, unicode_string()} + | {literal, true} + | {literal, false} + | {literal, null}. + + +%% this probably doesn't work properly +-type jsx_parser() :: fun((binary()) -> jsx_parser_result()). + +-type jsx_parser_result() :: + {event, jsx_event(), fun(() -> jsx_parser_result())} + | {incomplete, jsx_parser()} + | {error, badjson}. + + +-type supported_utf() :: utf8 + | utf16 + | {utf16, little} + | utf32 + | {utf32, little}. + + +%% eep0018 json specification +-type eep0018() :: eep0018_object() | eep0018_array(). + +-type eep0018_array() :: [eep0018_term()]. +-type eep0018_object() :: [{eep0018_key(), eep0018_term()}]. + +-type eep0018_key() :: binary() | atom(). + +-type eep0018_term() :: eep0018_array() + | eep0018_object() + | eep0018_string() + | eep0018_number() + | true | false | null. + +-type eep0018_string() :: binary(). + +-type eep0018_number() :: float() | integer(). + + +-type encoder_opts() :: [encoder_opt()]. +-type encoder_opt() :: {strict, true | false} + | {encoding, supported_utf()} + | {space, integer()} + | space + | {indent, integer()} + | indent. + + +-type decoder_opts() :: [decoder_opt()]. +-type decoder_opt() :: {strict, true | false} + | {comments, true | false} + | {encoding, supported_utf()} + | {label, atom | binary | existing_atom} + | {float, true | false}. + + +-type verify_opts() :: [verify_opt()]. +-type verify_opt() :: {strict, true | false} + | {encoding, auto | supported_utf()} + | {comments, true | false}. + + +-type format_opts() :: [format_opt()]. +-type format_opt() :: {strict, true | false} + | {encoding, auto | supported_utf()} + | {comments, true | false} + | {space, integer()} + | space + | {indent, integer()} + | indent + | {output_encoding, supported_utf()}. \ No newline at end of file diff --git a/include/jsx_decoder.hrl b/include/jsx_decoder.hrl index 6feb245..546d079 100644 --- a/include/jsx_decoder.hrl +++ b/include/jsx_decoder.hrl @@ -26,6 +26,8 @@ %% this file ?utfxshould take that into account +-spec parser(OptsList::jsx_opts()) -> jsx_parser(). + %% opts record for decoder -record(opts, { comments = false, diff --git a/src/jsx.erl b/src/jsx.erl index e1b22b5..16487f4 100644 --- a/src/jsx.erl +++ b/src/jsx.erl @@ -131,6 +131,8 @@ %% @spec parser() -> jsx_parser() %% @equiv parser([]) +-spec parser() -> jsx_parser(). + parser() -> parser([]). @@ -175,6 +177,8 @@ parser() -> %% %% @end +-spec parser(OptsList::jsx_opts()) -> jsx_parser(). + parser(OptsList) -> case proplists:get_value(encoding, OptsList, auto) of utf8 -> jsx_utf8:parser(OptsList) @@ -189,6 +193,8 @@ parser(OptsList) -> %% @spec json_to_term(JSON::binary()) -> eep0018() %% @equiv json_to_term(JSON, []) +-spec json_to_term(JSON::binary()) -> eep0018(). + json_to_term(JSON) -> json_to_term(JSON, []). @@ -241,6 +247,8 @@ json_to_term(JSON) -> %% %% @end +-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018(). + json_to_term(JSON, Opts) -> jsx_eep0018:json_to_term(JSON, Opts). @@ -248,6 +256,8 @@ json_to_term(JSON, Opts) -> %% @spec term_to_json(JSON::eep0018()) -> binary() %% @equiv term_to_json(JSON, []) +-spec term_to_json(JSON::eep0018()) -> binary(). + term_to_json(JSON) -> term_to_json(JSON, []). @@ -286,7 +296,9 @@ term_to_json(JSON) -> %%

indent each 'level' of the json structure by N spaces. default is %% zero

%% -%% @end +%% @end + +-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary(). term_to_json(JSON, Opts) -> jsx_eep0018:term_to_json(JSON, Opts). @@ -295,6 +307,8 @@ term_to_json(JSON, Opts) -> %% @spec is_json(JSON::binary()) -> true | false %% @equiv is_json(JSON, []) +-spec is_json(JSON::binary()) -> true | false. + is_json(JSON) -> is_json(JSON, []). @@ -326,6 +340,8 @@ is_json(JSON) -> %% %% @end +-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false. + is_json(JSON, Opts) -> jsx_verify:is_json(JSON, Opts). @@ -333,6 +349,8 @@ is_json(JSON, Opts) -> %% @spec format(JSON::binary()) -> binary() %% @equiv format(JSON, []) +-spec format(JSON::binary()) -> binary() | iolist(). + format(JSON) -> format(JSON, []). @@ -387,6 +405,8 @@ format(JSON) -> %% %% @end +-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist(). + format(JSON, Opts) -> jsx_format:format(JSON, Opts). @@ -395,6 +415,9 @@ format(JSON, Opts) -> %% @doc fake the jsx api for any list. useful if you want to serialize a %% structure to json using the pretty printer, or verify a sequence could be %% valid json + +-spec eventify(List::list()) -> jsx_parser_result(). + eventify([]) -> fun() -> {incomplete, fun(List) when is_list(List) -> diff --git a/src/jsx_eep0018.erl b/src/jsx_eep0018.erl index fdbe1af..c648f4e 100644 --- a/src/jsx_eep0018.erl +++ b/src/jsx_eep0018.erl @@ -39,6 +39,8 @@ +-spec json_to_term(JSON::binary(), Opts::decoder_opts()) -> eep0018(). + json_to_term(JSON, Opts) -> P = jsx:parser(opts_to_jsx_opts(Opts)), case proplists:get_value(strict, Opts, true) of @@ -51,6 +53,9 @@ json_to_term(JSON, Opts) -> %% converting erlang terms to json strings, but it expects a jsx event %% iterator. luckily, the mapping from erlang terms to jsx events is %% straightforward and the iterator can be faked with an anonymous function + +-spec term_to_json(JSON::eep0018(), Opts::encoder_opts()) -> binary(). + term_to_json(List, Opts) -> case proplists:get_value(strict, Opts, true) of true when is_list(List) -> continue diff --git a/src/jsx_format.erl b/src/jsx_format.erl index 970aa83..d6fbf4d 100644 --- a/src/jsx_format.erl +++ b/src/jsx_format.erl @@ -40,6 +40,8 @@ -endif. + +-spec format(JSON::binary(), Opts::format_opts()) -> binary() | iolist(). format(JSON, Opts) when is_binary(JSON) -> P = jsx:parser(extract_parser_opts(Opts)), diff --git a/src/jsx_verify.erl b/src/jsx_verify.erl index 05097c9..34148ea 100644 --- a/src/jsx_verify.erl +++ b/src/jsx_verify.erl @@ -40,6 +40,8 @@ +-spec is_json(JSON::binary(), Opts::verify_opts()) -> true | false. + is_json(JSON, Opts) -> Encoding = proplists:get_value(encoding, Opts, utf8), Comments = proplists:get_value(comments, Opts, false),