SkillAgentSearch skills...

Jsonx

JSONX is an Erlang library for efficient decode and encode JSON, written in C.

Install / Use

/learn @iskra/Jsonx
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

JSONX is an Erlang library for efficient JSON decoding and encoding, implemented in Erlang NIFs. Works with binaries as strings, arrays as lists and only knows how to decode UTF-8 (and ASCII).

JSONX IS VERY FAST!

Check out a benchmark si14/erl_json_test or davisp/erljson_bench and record encoding tests in /test/bench_encode_records.erl

INSTALLATION and DOCUMENTATION

  • cd jsonx
  • make
  • make doc
  • firefox doc/index.html&

JSONX can encode and decode Erlang records!

-module(record_example).
-compile(export_all).

-record(person,  {name, age, friends}).
-record(person2, {name, age, phone}).

encoder1() ->
    jsonx:encoder([{person,   record_info(fields, person)},
                   {person2,  record_info(fields, person2)} ]).

decoder1() ->
    jsonx:decoder([{person,   record_info(fields, person)},
                   {person2,  record_info(fields, person2)}]).

nonstrict_decoder1() ->
    jsonx:decoder([{person,   record_info(fields, person)},
                   {person2,  record_info(fields, person2)}],
		  [{format, proplist}]).
1> c(records_examples).
{ok,records_examples}

2>  rr(record_examples).
[person,person2]

3> BabaYaga = #person2{name = <<"BabaYaga">>, age = 118, phone = <<"666-66-66">>}.
#person2{name = <<"BabaYaga">>,age = 118,
         phone = <<"666-66-66">>}

4>  Vasya = #person{name = <<"Vasya">>, age = 18, friends = [BabaYaga]}.
#person{name = <<"Vasya">>,age = 18,
        friends = [#person2{name = <<"BabaYaga">>,age = 118,
                            phone = <<"666-66-66">>}]}

5> Encoder = record_examples:encoder1().
#Fun<jsonx.0.45888425>

6> Decoder = record_examples:decoder1().
#Fun<jsonx.1.21317315>

7> Json = Encoder(BabaYaga).
<<"{\"name\": \"BabaYaga\",\"age\": 118,\"phone\": \"666-66-66\"}">>

8> Decoder(Json).
#person2{name = <<"BabaYaga">>,age = 118,
         phone = <<"666-66-66">>}
9> Json2 = Encoder(Vasya).
<<"{\"name\": \"Vasya\",\"age\": 18,\"friends\": [{\"name\": \"BabaYaga\",\"age\": 118,\"phone\": \"666-66-66\"}]}">>

10> Decoder(Json2).
#person{name = <<"Vasya">>,age = 18,
        friends = [#person2{name = <<"BabaYaga">>,age = 118,
                            phone = <<"666-66-66">>}]}

11> Json3 = <<"[{\"name\": \"BabaYaga\",\"age\": 118,\"phone\": \"666-66-66\"}, {\"record\": \"undefined\", \"strict\": false}]">>.
<<"[{\"name\": \"BabaYaga\",\"age\": 118,\"phone\": \"666-66-66\"}, {\"record\": \"undefined\", \"strict\": false}]">>

12> Decoder(Json3).
{error,undefined_record,64}

13>  NonStrictDecoder = record_examples:nonstrict_decoder1().
#Fun<jsonx.2.71844966>

14> JTerm =  NonStrictDecoder(Json3).
[#person2{name = <<"BabaYaga">>,age = 118,
          phone = <<"666-66-66">>},
 [{<<"record">>,<<"undefined">>},{<<"strict">>,false}]]

15> Encoder(JTerm).
<<"[{\"name\": \"BabaYaga\",\"age\": 118,\"phone\": \"666-66-66\"},{\"record\":\"undefined\",\"strict\":false}]">>

Examples encoding JSON

1>  jsonx:encode([1, 2.3, true, false, null, atom, <<"string">>, []]).
<<"[1,2.3,true,false,null,\"atom\",\"string\",[]]">>

%% Object as proplist
2>  jsonx:encode( [{name, <<"Ivan">>}, {age, 33}, {phones, [3332211, 4443322]}] ).
<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>

%% Object as struct
3>  jsonx:encode( {struct, [{name, <<"Ivan">>}, {age, 33}, {phones, [3332211, 4443322]}]} ).
<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>

%% Object as eep18 propsal
4>  jsonx:encode( {[{name, <<"Ivan">>}, {age, 33}, {phones, [3332211, 4443322]}]} ).
<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>

Examples decoding JSON

1> jsonx:decode(<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>).
{[{<<"name">>,<<"Ivan">>},
  {<<"age">>,33},
  {<<"phones">>,[3332211,4443322]}]}

2> jsonx:decode(<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>, [{format, eep18}]).
{[{<<"name">>,<<"Ivan">>},
  {<<"age">>,33},
  {<<"phones">>,[3332211,4443322]}]}

3> jsonx:decode(<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>, [{format, proplist}]).
[{<<"name">>,<<"Ivan">>},
 {<<"age">>,33},
 {<<"phones">>,[3332211,4443322]}]

4> jsonx:decode(<<"{\"name\":\"Ivan\",\"age\":33,\"phones\":[3332211,4443322]}">>, [{format, struct}]). 
{struct,[{<<"name">>,<<"Ivan">>},
         {<<"age">>,33},
         {<<"phones">>,[3332211,4443322]}]}

Example streaming parse

More example see examples/stream_example.erl .

1> D = jstream:new_decoder(<<"{\"key1\": \"val1\",\n">>).
<<>>

2> jstream:get_event(D).
start_map

3> jstream:get_event(D).
{map_key,<<"key1">>}

4> jstream:get_event(D).
<<"val1">>

5> jstream:get_event(D).
parse_buf

6> ok = jstream:update_decoder(D, <<"\"key2\": \"val2\"}\n">>).
ok

7> jstream:get_event(D).
{map_key,<<"key2">>}

8> jstream:get_event(D).
<<"val2">>

9> jstream:get_event(D).
end_map

10> jstream:get_event(D).
{parse_end,<<>>}

Mapping (JSON -> Erlang)

null             :-> null
true             :-> true
false            :-> false
"string"         :-> <<"binary">>
[1, 2.3, []]     :-> [1, 2.3, []]
{"this": "json"} :-> {[{<<"this">>: <<"json">>}]}         %% default eep18
{"this": "json"} :-> [{<<"this">>: <<"json">>}]           %% optional proplist
{"this": "json"} :-> {struct, [{<<"this">>: <<"json">>}]} %% optional struct
JSONObject       :-> #rec{...}                            %% decoder must be predefined

Mapping (Erlang -> JSON)

null                                 :-> null
true                                 :-> true
false                                :-> false
atom                                 :-> "atom"
<<"str">>                            :-> "str"
[1, 2.99]                            :-> [1, 2.99]
{struct, [{<<"this">>: <<"json">>}]} :-> {"this": "json"}
[{<<"this">>: <<"json">>}]           :-> {"this": "json"}
{[{<<"this">>: <<"json">>}]}         :-> {"this": "json"}
{json, IOList}                       :-> `iolist_to_binary(IOList)`  %% include with no validation
#rec{...}                            :-> JSONObject                  %% encoder must be predefined

Related Skills

View on GitHub
GitHub Stars91
CategoryDevelopment
Updated1y ago
Forks32

Languages

C

Security Score

65/100

Audited on Jan 31, 2025

No findings