Home

Awesome

json

a high level library for working with json in erlang (17.0+)

json is built via rebar, and continuous integration testing provided by travis-ci

current status: Build Status

json is released under the terms of the MIT license

copyright 2014 alisdair sullivan

notes

erlang 17.0+ is required to use this library due to it's reliance on the new map implementation

dependencies

jsx is used when converting between erlang binary() and json() types

jsonpointer is used for handling json paths in accordance with rfc6901.

index

quickstart

to build library and run tests

$ rebar get-deps
$ rebar compile
$ rebar eunit

conversion between json and utf8 binaries####

convert between json() and binary() erlang types.

ExampleJSON will be used as an example JSON input for the rest of the quickstart.

1> ExampleJSON = json:from_binary(<<"{\"library\": \"json\", \"awesome\": true,
1> \"list\": [{\"a\": 1}, {\"b\": 2}, {\"c\": 3} ]}">>).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}
1> json:to_binary(ExampleJSON).
<<"{\"awesome\":true,\"library\":\"json\",\"list\":[{\"a\":1},{\"b\":2},{\"c\":3}]}">>

get json at supplied json path

1> json:get(<<"/list/0/a">>, ExampleJSON).
1
2> json:get([list, 0, a], ExampleJSON).
1
3> GetJSONFun = json:get([list, 0, a]).
#Fun<json.0.18938731>
4> GetJSONFun(ExampleJSON).
1

add json to supplied json path

1> json:add([addition], <<"1+1">>, ExampleJSON).
#{<<"addition">> => <<"1+1">>,
  <<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}
2> json:add([recursion], ExampleJSON, ExampleJSON).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}],
  <<"recursion">> => #{<<"awesome">> => true,
    <<"library">> => <<"json">>,
    <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}}
3> json:add([map], #{<<"test2">> => 50}, ExampleJSON).                                  
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}],
  <<"map">> => #{<<"test2">> => 50}}
4> json:add(<<"/listtest">>, [50, <<"listadd">>, testatom], ExampleJSON).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}],
  <<"listtest">> => [50,<<"listadd">>,testatom]}

remove json at supplied json path

1> json:remove([list, 2], ExampleJSON).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2}]}

replace json at supplied json path with new json####

1> json:replace([awesome], <<"json in erlang!">> ,ExampleJSON).                                                
#{<<"awesome">> => <<"json in erlang!">>,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}

copy json from one json path to another

1> json:copy([list],[copiedlist],ExampleJSON).
#{<<"awesome">> => true,
  <<"copiedlist">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}], 
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}

move json from one json path to another

1> json:move([library], [newlibrary], ExampleJSON).
#{<<"awesome">> => true,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}],
  <<"newlibrary">> => <<"json">>}

patch json using a list of ops

ExampleJSON = json:from_binary(<<"{\"library\": \"json\", \"awesome\": true, \"list\": [{\"a\": 1}, {\"b\": 2}, {\"c\": 3} ]}">>).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}]}
2> PatchEx = #{<<"op">> => <<"add">>, <<"path">> => [patchtest], <<"value">> => true}.
#{<<"op">> => <<"add">>,<<"path">> => [patchtest],<<"value">> => true}
3> json:patch([PatchEx], ExampleJSON).
#{<<"awesome">> => true,
  <<"library">> => <<"json">>,
  <<"list">> => [#{<<"a">> => 1},#{<<"b">> => 2},#{<<"c">> => 3}],
  <<"patchtest">> => true}

fold functions over json at supplied json path

1> JSON = #{<<"foo">> => <<"bar">>}.
#{<<"foo">> => <<"bar">>}
2> json:fold([json:test(<<"/foo">>, <<"bar">>),
2>   json:copy(<<"/foo">>, <<"/qux">>),
2>   json:test(<<"/qux">>, <<"bar">>),
2>   json:replace(<<"/qux">>, <<"baz">>),
2>   json:remove(<<"/foo">>),
2>   json:move(<<"/qux">>, <<"/foo">>),
2>   json:test(<<"/foo">>, <<"baz">>)
2> ], JSON).
#{<<"foo">> => <<"baz">>}

return json keys at supplied json path

2> json:keys([], ExampleJSON).                   
[<<"awesome">>,<<"library">>,<<"list">>]

description

a high level library for erlang 17.0+. leverages the new maps to support the json spec

data types

path() type

path() :: binary() | [atom() | integer() | binary()]

json() type

json() :: #{binary() => json()}
  | [json()]
  | integer()
  | float()
  | binary()
  | true
  | false
  | null

exports

from_binary/1

from_binary(JSON) -> json()

JSON = binary()

uses jsx's decoder/3 to convert a binary() to json()

to_binary/1

to_binary(JSON) -> binary()

JSON = json()

uses jsx's encode to convert json() to binary()

minify/1

minify(JSON) -> binary()

JSON = json()

removes all non-semantic whitespace from a json binary

prettify/1

prettify(JSON) -> binary()

JSON = json()

formats a json binary for output with spaces and newlines

get/1,2

get(Path, JSON) -> json()
get(Path) -> fun((JSON) -> json())

Path = path()
JSON = json()

get json() at supplied path in JSON, or return an anonymous function to be applied to a given JSON value

add/2,3

add(Path, Value, JSON) -> json()
add(Path, Value) -> fun((JSON) -> json())

Path = path()
Value = json()
JSON = json()

add Value at supplied Path in JSON, or return an anonymous function to do the same for a supplied JSON value

remove/1,2

remove(Path, JSON) -> json()
remove(Path) -> fun((JSON) -> json())

Path = path()
JSON = json()

remove json() at Path in JSON, or return an anonymous function to do the same for a supplied JSON value

replace/2,3

replace(Path, Value, JSON) -> json()
replace(Path, Value) -> fun((JSON) -> json())

Path = path()
Value = json()
JSON = json()

replace Path in JSON with Value, or return an anonymous function to do the same for a supplied JSON value

copy/2,3

copy(From, To, JSON) -> json()
copy(From, To) -> fun((JSON) -> json())

From = path()
To = path()
JSON = json()

copy a json() term From a path To another path in JSON, or return an anonymous function to do the same for a supplied JSON value

move/2,3

move(From, To, JSON) -> json()
move(From, To) -> fun((JSON) -> json())

From = path()
To = path()
JSON = json()

Move a json() term From a path To another path in JSON, or return an anonymous function to do the same for a supplied JSON.

test/2,3

test(Path, Value, JSON) -> json()
test(Path, Value) -> fun((JSON) -> json())

Path = path()
Value = json()
JSON = json()

test the existence of Value at a given Path in JSON, or return an anonymous function to do the same for a supplied JSON value

apply/2,3

apply(Path, Fun, JSON) -> json()
apply(Path, Fun)  -> fun((JSON) -> json())

apply function Fun at a given Path in JSON, or return an anonymous function to do the same for a supplied JSON value

patch/2

patch(Ops, JSON) -> json()

Ops = [#{<<"op">> => Op, <<"path">> => Path, Arg => Value}]
JSON = json()
Op = #{<<"op">> => <<"add">>, <<"path">> => Path, <<"value">> => Value}
   | #{<<"op">> => <<"remove">>, <<"path">> => Path}
   | #{<<"op">> => <<"replace">>, <<"path">> => Path, <<"value">> => Value}
   | #{<<"op">> => <<"copy">>, <<"path">> => Path, <<"from">> => Path}
   | #{<<"op">> => <<"move">>, <<"path">> => Path, <<"from">> => Path}
   | #{<<"op">> => <<"test">>, <<"path">> => Path, <<"value">> => Value}
Path = path()
Value = json()

patches JSON using the methods supplied by the maps in Ops.

fold/2

fold(Funs, JSON) -> json().

Funs = [function()]
JSON = json()

fold a list of functions, Funs, over JSON

keys/2

keys(Path, JSON) -> [binary()]

return a list of binary() keys at Path in JSON

acknowledgements

bobthenameless for writing the documentation