Module jsone

JSON decoding/encoding module.

Description

JSON decoding/encoding module

Data Types

common_option()

common_option() = undefined_as_null

undefined_as_null:
- Treats undefined in Erlang as the conversion target for null in JSON. This means that undefined will be encoded to null and null will be decoded to undefined

datetime_encode_format()

datetime_encode_format() = datetime_format() | {Format::datetime_format(), TimeZone::timezone()}

Datetime encoding format.

The default value of TimeZone is utc.

  %
  % Universal Time
  %
  > jsone:encode({{2000, 3, 10}, {10, 3, 58}}, [{datetime_format, iso8601}]).
  <<"\"2000-03-10T10:03:58Z\"">>
 
  %
  % Local Time (JST)
  %
  > jsone:encode({{2000, 3, 10}, {10, 3, 58}}, [{datetime_format, {iso8601, local}}]).
  <<"\"2000-03-10T10:03:58+09:00\"">>
 
  %
  % Explicit TimeZone Offset
  %
  > jsone:encode({{2000, 3, 10}, {10, 3, 58}}, [{datetime_format, {iso8601, -2*60*60}}]).
  <<"\"2000-03-10T10:03:58-02:00\"">>

datetime_format()

datetime_format() = iso8601

decode_option()

decode_option() = {object_format, tuple | proplist | map} | {allow_ctrl_chars, boolean()} | reject_invalid_utf8 | {keys, binary | atom | existing_atom | attempt_atom} | common_option()

object_format:
- Decoded JSON object format
- tuple: An object is decoded as {[]} if it is empty, otherwise {[{Key, Value}]}.
- proplist: An object is decoded as [{}] if it is empty, otherwise [{Key, Value}].
- map: An object is decoded as #{} if it is empty, otherwise #{Key => Value}.
- default: map if OTP version is OTP-17 or more, tuple otherwise

allow_ctrl_chars:
- If the value is true, strings which contain unescaped control characters will be regarded as a legal JSON string
- default: false

reject_invalid_utf8:
- Rejects JSON strings which contain invalid UTF-8 byte sequences

keys:
Defines way how object keys are decoded. The default value is binary. The option is compatible with labels option in jsx.
- binary: The key is left as a string which is encoded as binary. It's default and backward compatible behaviour.
- atom: The key is converted to an atom. Results in badarg if Key value regarded as UTF-8 is not a valid atom.
- existing_atom: Returns existing atom. Any key value which is not existing atom raises badarg exception.
- attempt_atom: Returns existing atom as existing_atom but returns a binary string if fails find one.

encode_option()

encode_option() = native_utf8 | native_forward_slash | canonical_form | {float_format, [float_format_option()]} | {datetime_format, datetime_encode_format()} | {object_key_type, string | scalar | value} | {space, non_neg_integer()} | {indent, non_neg_integer()} | common_option()

native_utf8:
- Encodes non ASCII UTF-8 characters as a human-readable(non-escaped) string

native_forward_slash:
- Prevents forward slashes in a JSON string from being escaped

canonical_form:
- produce a canonical form of a JSON document

{float_format, Optoins}: - Encodes a float()` value in the format which specified by `Options
- default: [{scientific, 20}]

{datetime_format, Format}`: - Encodes a `calendar:datetime()` value in the format which specified by `Format
- default: {iso8601, utc}

object_key_type: - Allowable object key type
- string: Only string values are allowed (i.e. json_string() type)
- scalar: In addition to string, following values are allowed: nulls, booleans, numerics (i.e. json_scalar() type)
- value: Any json compatible values are allowed (i.e. json_value() type)
- default: string
- NOTE: If scalar or value option is specified, non json_string() key will be automatically converted to a binary() value (e.g. 1 => <<"1">>, #{} => <<"{}">>)

{space, N}:
- Inserts N spaces after every commna and colon
- default: 0

{indent, N}:
- Inserts a newline and N spaces for each level of indentation
- default: 0

float_format_option()

float_format_option() = {scientific, Decimals::0..249} | {decimals, Decimals::0..253} | compact

scientific:
- The float will be formatted using scientific notation with Decimals digits of precision.

decimals:
- The encoded string will contain at most Decimals number of digits past the decimal point.
- If compact is provided the trailing zeros at the end of the string are truncated.

For more details, see erlang:flaot_to_list/2.

  > jsone:encode(1.23).
  <<"1.22999999999999998224e+00">>
 
  > jsone:encode(1.23, [{float_format, [{scientific, 4}]}]).
  <"1.2300e+00">>
 
  > jsone:encode(1.23, [{float_format, [{scientific, 1}]}]).
  <<"1.2e+00">>
 
  > jsone:encode(1.23, [{float_format, [{decimals, 4}]}]).
  <<"1.2300">>
 
  > jsone:encode(1.23, [{float_format, [{decimals, 4}, compact]}]).
  <<"1.23">>

json_array()

json_array() = [json_value()]

json_boolean()

json_boolean() = boolean()

json_number()

json_number() = number()

json_object()

json_object() = json_object_format_tuple() | json_object_format_proplist() | json_object_format_map()

json_object_format_map()

json_object_format_map() = map()

json_object_format_proplist()

json_object_format_proplist() = [{}] | json_object_members()

json_object_format_tuple()

json_object_format_tuple() = {json_object_members()}

json_object_members()

json_object_members() = [{json_string(), json_value()}]

json_scalar()

json_scalar() = json_boolean() | json_number() | json_string()

json_string()

json_string() = binary() | atom() | calendar:datetime()

NOTE: decode/1 always returns binary() value

json_term()

json_term() = {{json, iolist()}} | {{json_utf8, unicode:chardata()}}

json_term() allows inline already encoded JSON value. json variant expects byte encoded utf8 data values as list members. json_utf8 expect Unicode code points as list members. Binaries are copied "as is" in both variants except json_utf8 will check if binary contain valid UTF-8 encoded data. In short, json uses erlang:iolist_to_binary/1 and json_utf8 uses unicode:chardata_to_binary/1 for encoding.

A simple example is worth a thousand words.

  1> S = "hélo".
  "hélo"
  2> shell:strings(false).
  true
  3> S.
  [104,233,108,111]
  4> B = jsone:encode({{json, S}}).  % invalid UTF-8
  <<104,233,108,111>>
  5> B2 = jsone:encode({{json_utf8, S}}). % valid UTF-8
  <<104,195,169,108,111>>
  6> jsone:encode({{json, B}}).
  <<104,233,108,111>>
  7> jsone:encode({{json_utf8, B}}).
  ** exception error: {invalid_json_utf8,<<104>>,<<233,108,111>>}
       in function  jsone_encode:value/4
          called as jsone_encode:value({json_utf8,<<104,233,108,111>>},
                                       [],<<>>,
                                       {encode_opt_v2,false,
                                                      [{scientific,20}],
                                                      {iso8601,0},
                                                      string,0,0})
       in call from jsone:encode/2 (/home/hynek/work/altworx/jsone/_build/default/lib/jsone/src/jsone.erl, line 302)
  8> jsone:encode({{json_utf8, B2}}).
  <<104,195,169,108,111>>
  9> shell:strings(true).
  false
  10> jsone:encode({{json_utf8, B2}}).
  <<"hélo"/utf8>>
  11> jsone:encode({{json, binary_to_list(B2)}}). % UTF-8 encoded list leads to valid UTF-8
  <<"hélo"/utf8>>

json_value()

json_value() = json_number() | json_string() | json_array() | json_object() | json_boolean() | null | undefined | json_term()

stack_item()

stack_item() = {Module::module(), Function::atom(), Arity::arity() | (Args::[term()]), Location::[{file, Filename::string()} | {line, Line::pos_integer()}]}

An item in a stack back-trace.

Note that the erlang module already defines the same stack_item/0 type, but it is not exported from the module. So, maybe as a temporary measure, we redefine this type for passing full dialyzer analysis.

timezone()

timezone() = utc | local | utc_offset_seconds()

utc_offset_seconds()

utc_offset_seconds() = -86399..86399

Function Index

decode/1Equivalent to decode(Json, []).
decode/2Decodes an erlang term from json text (a utf8 encoded binary).
encode/1Equivalent to encode(JsonValue, []).
encode/2Encodes an erlang term into json text (a utf8 encoded binary).
try_decode/1Equivalent to try_decode(Json, []).
try_decode/2Decodes an erlang term from json text (a utf8 encoded binary).
try_encode/1Equivalent to try_encode(JsonValue, []).
try_encode/2Encodes an erlang term into json text (a utf8 encoded binary).

Function Details

decode/1

decode(Json::binary()) -> json_value()

Equivalent to decode(Json, []).

decode/2

decode(Json::binary(), Options::[decode_option()]) -> json_value()

Decodes an erlang term from json text (a utf8 encoded binary)

Raises an error exception if input is not valid json

  > jsone:decode(<<"1">>, []).
  1
 
  > jsone:decode(<<"wrong json">>, []).
  ** exception error: bad argument
      in function  jsone_decode:number_integer_part/4
         called as jsone_decode:number_integer_part(<<"wrong json">>,1,[],<<>>)
      in call from jsone:decode/1 (src/jsone.erl, line 71)

encode/1

encode(JsonValue::json_value()) -> binary()

Equivalent to encode(JsonValue, []).

encode/2

encode(JsonValue::json_value(), Options::[encode_option()]) -> binary()

Encodes an erlang term into json text (a utf8 encoded binary)

Raises an error exception if input is not an instance of type json_value()

  > jsone:encode([1, null, 2]).
  <<"[1,null,2]">>
 
  > jsone:encode([1, self(), 2]).  % A pid is not a json value
  ** exception error: bad argument
       in function  jsone_encode:value/3
          called as jsone_encode:value(<0,34,0>,[{array_values,[2]}],<<"[1,">>)
       in call from jsone:encode/1 (src/jsone.erl, line 97)

try_decode/1

try_decode(Json::binary()) -> {ok, json_value(), Remainings::binary()} | {error, {Reason::term(), [stack_item()]}}

Equivalent to try_decode(Json, []).

try_decode/2

try_decode(Json::binary(), Options::[decode_option()]) -> {ok, json_value(), Remainings::binary()} | {error, {Reason::term(), [stack_item()]}}

Decodes an erlang term from json text (a utf8 encoded binary)

  > jsone:try_decode(<<"[1,2,3] \"next value\"">>, []).
  {ok,[1,2,3],<<" \"next value\"">>}
 
  > jsone:try_decode(<<"wrong json">>, []).
  {error,{badarg,[{jsone_decode,number_integer_part,
                                [<<"wrong json">>,1,[],<<>>],
                                [{line,208}]}]}}

try_encode/1

try_encode(JsonValue::json_value()) -> {ok, binary()} | {error, {Reason::term(), [stack_item()]}}

Equivalent to try_encode(JsonValue, []).

try_encode/2

try_encode(JsonValue::json_value(), Options::[encode_option()]) -> {ok, binary()} | {error, {Reason::term(), [stack_item()]}}

Encodes an erlang term into json text (a utf8 encoded binary)

  > jsone:try_encode([1, null, 2]).
  {ok,<<"[1,null,2]">>}
 
  > jsone:try_encode([1, hoge, 2]).  % 'hoge' atom is not a json value
  {error,{badarg,[{jsone_encode,value,
                                [hoge,[{array_values,[2]}],<<"[1,">>],
                                [{line,86}]}]}}


Generated by EDoc