Skip to content

Repository files navigation

jsone

hex.pm versionBuild StatusCode CoverageLicense: MIT

An Erlang library for encoding, decoding JSON data.

Features

  • Provides simple encode/decode function only
  • RFC7159-compliant
  • Supports UTF-8 encoded binary
  • Pure Erlang
  • Highly Efficient
    • Maybe one of the fastest JSON library (except those which are implemented in NIF)
    • Decode function is written in continuation-passing style(CPS)

QuickStart

# clone
$ git clone git://github.com/sile/jsone.git
$ cd jsone
# compile
$ make compile
# run tests
$ make eunit
# dialyze
$ make dialyze
# Erlang shell
$ make start
1> jsone:decode(<<"[1,2,3]">>).[1,2,3]

Usage Example

%% Decode>jsone:decode(<<"[1,2,3]">>).
[1,2,3]
>jsone:decode(<<"{\"1\":2}">>).
#{<<"1">> =>2}
>jsone:decode(<<"{\"1\":2}">>, [{object_format, tuple}]). % tuple format
{[{<<"1">>, 2}]}
>jsone:decode(<<"{\"1\":2}">>, [{object_format, proplist}]). % proplist format
[{<<"1">>, 2}]
>jsone:try_decode(<<"[1,2,3] \"next value\"">>). % try_decode/1 returns remaining (unconsumed binary)
{ok,[1,2,3],<<"\"next value\"">>}
% error: raises exception>jsone:decode(<<"1.x">>).
**exceptionerror: badargumentinfunctionjsone_decode:number_fraction_part_rest/6calledasjsone_decode:number_fraction_part_rest(<<"x">>,1,1,0,[],<<>>)
incallfromjsone:decode/1 (src/jsone.erl, line71)
% error: returns {error, Reason}>jsone:try_decode(<<"1.x">>).
{error,{badarg,[{jsone_decode,number_fraction_part_rest,
[<<"x">>,1,1,0,[],<<>>],
[{line,228}]}]}}
%% Encode>jsone:encode([1,2,3]).
<<"[1,2,3]">>
>jsone:encode(#{<<"key">> => <<"value">>}). % map format>jsone:encode({[{<<"key">>, <<"value">>}]}). % tuple format>jsone:encode([{<<"key">>, <<"value">>}]). % proplist format
<<"{\"key\":\"value\"}">>
>jsone:encode(#{key=> <<"value">>}). % atom key is allowed
<<"{\"key\":\"value\"}">>
% error: raises exception>jsone:encode(#{123=> <<"value">>}). % non binary|atom key is not allowed**exceptionerror: badargumentinfunctionjsone_encode:object_members/3calledasjsone_encode:object_members([{123,<<"value">>}],[],<<"{">>)
incallfromjsone:encode/1 (src/jsone.erl, line97)
% error: returns {error, Reason}>jsone:try_encode({[{123, <<"value">>}]}).
{error,{badarg,[{jsone_encode,object_members,
[[{123,<<"value">>}],[],<<"{">>],
[{line,138}]}]}}
% 'object_key_type' option allows non-string object key>jsone:encode({[{123, <<"value">>}]}, [{object_key_type, scalar}]).
<<"{\"123\":\"value\"}">>
% 'undefined_as_null' option allows encoding atom undefined as null>jsone:encode(undefined,[undefined_as_null]).
<<"null">>
%% Pretty Print>Data= [true, #{<<"1">> =>2, <<"array">> => [[[[1]]], #{<<"ab">> => <<"cd">>}, [], #{}, false]}, null].
>io:format("~s\n", [jsone:encode(Data, [{indent, 2}, {space, 1}])]).
[
true,
{
"1": 2,
"array": [
[
[
[
1
]
]
],
{
"ab": "cd"
},
[],
{},
false
]
},
null
]
ok%% Number Format>jsone:encode(1). % integer
<<"1">>
>jsone:encode(1.23). % float
<<"1.22999999999999998224e+00">> % default: scientific notation>jsone:encode(1.23, [{float_format, [{decimals, 4}]}]). % decimal notation
<<"1.2300">>
>jsone:encode(1.23, [{float_format, [{decimals, 4}, compact]}]). % compact decimal notation
<<"1.23">>
%% If you want to safely cast object keys to atoms, the `attempt_atom' option will help.>jsone:decode(<<"{\"hello\": \"world\"}">>, [{keys, attempt_atom}]).
#{<<"hello">> => <<"world">>} % There is no atom named "hello", so the key is decoded as binary.>hello. % Create "hello" atom.hello>jsone:decode(<<"{\"hello\": \"world\"}">>, [{keys, attempt_atom}]).
#{hello=> <<"world">>} % Now, the key is decoded as atom.

Data Mapping (Erlang <=> JSON)

Erlang JSON Erlang
=================================================================================================
null -> null -> null
undefined -> null -> undefined % undefined_as_null
true -> true -> true
false -> false -> false
<<"abc">> -> "abc" -> <<"abc">>
abc -> "abc" -> <<"abc">> % non-special atom is regarded as a binary
{{2010,1,1},{0,0,0}} -> "2010-01-01T00:00:00Z" -> <<"2010-01-01T00:00:00Z">> % datetime*
{{2010,1,1},{0,0,0.0}} -> "2010-01-01T00:00:00.000Z" -> <<"2010-01-01T00:00:00.000Z">> % datetime*
123 -> 123 -> 123
123.4 -> 123.4 -> 123.4
[1,2,3] -> [1,2,3] -> [1,2,3]
{[]} -> {} -> {[]} % object_format=tuple
{[{key, <<"val">>}]} -> {"key":"val"} -> {[{<<"key">>, <<"val">>}]} % object_format=tuple
[{}] -> {} -> [{}] % object_format=proplist
[{<<"key">>, val}] -> {"key":"val"} -> [{<<"key">>, <<"val">>}] % object_format=proplist
#{} -> {} -> #{} % object_format=map
#{key => val} -> {"key":"val"} -> #{<<"key">> => <<"val">>} % object_format=map
{{json, IOList}} -> Value -> ~~~ % UTF-8 encoded term**
{{json_utf8, Chars}} -> Value -> ~~~ % Unicode code points**

* see jsone:datetime_encode_format()

** {json, IOList} and {json_utf8, Chars} allows inline already encoded JSON values. For example, you obtain JSON encoded data from database so you don't have to decode it first and encode again. See jsone:json_term().

API

See EDoc Document

Benchmark

The results of poison benchmarking.

See the benchmark/README.md file for more information.

Encoding (Unit: IPS=inputs per second)

Input data \ LibraryJasonjiffyJSON*jsoneJSXPoisonTiny
Blockchain2.77 K4.55 K0.45 K1.44 K (3)0.60 K1.30 K0.99 K
Giphy230.65487.6747.73114.57 (4)44.97114.57113.59
GitHub880.031566.67139.79300.26 (5)99.68424.75455.07
GovTrack6.5724.922.335.35 (5)2.657.067.86
Issue 9022.8021.920.7714.30 (3)5.3312.6012.95
JSON Generateor200.40606.8142.45147.12 (4)68.73187.95123.93
Pokedex209.51776.6762.60161.45 (4)69.87190.93125.16
UTF-8 unescaped626.256644.531167.89582.41 (4)273.48401.44220.14

* Only JSON didn't escape non-ASCII unicode characters on the encoding

Decoding (Unit: IPS=inputs per second)

Input data \ LibraryJasonjiffyJSONjsoneJSXPoisonTiny
Blockchain2.75 K2.62 K0.35 K2.21 K (3)0.89 K1.32 K1.49 K
Giphy212.18243.4535.67109.11 (5)64.32110.76114.54
GitHub973.411052.94137.02662.39 (3)271.97438.79542.67
GovTrack10.778.320.805.08 (3)2.813.583.65
Issue 9017.8541.160.8810.79 (5)6.0213.6314.03
JSON Generateor320.79243.9325.16184.23 (3)111.24135.47139.78
JSON Generateor (Pretty)273.57205.0925.04158.82 (3)97.93123.31136.65
Pokedex527.63285.4333.70245.36 (3)140.90172.45152.59
UTF-8 escaped1224.487923.08326.43573.70 (4)550.36918.21520.31
UTF-8 unescaped5.56 K12.54 K1.35 K5.09 K (3)3.30 K4.39 K1.46 K

License

This library is released under the MIT License.

See the COPYING file for full license information.

About

Erlang JSON library

Topics

Resources

Stars

294 stars

Watchers

26 watching

Forks

Releases

Packages

Used by

Contributors

Languages