Skip to content

Examples

Eric Pailleau edited this page Apr 29, 2018 · 20 revisions

Examples

Convert JSON object to record specification

Create a record definition file from a JSON sample :

1> A = jason:decode_file("priv/ex1.json",[{mode, record}, {to, "/tmp/records.hrl"}]).
{'22207878',{'34707836',"example glossary",
                            {'6257036',"S",
                                       {'131402670',{'49933946',"SGML","SGML",
                                                                "Standard Generalized Markup Language","SGML",
                                                                "ISO 8879:1986",
                                                                {'111785629',"A meta-markup language, used to create markup languages such as DocBook.",
                                                                             ["GML","XML"]},
                                                                "markup"}}}}}

Looking at content of record definition file :

$ cat /tmp/records.hrl
-record('111785629', {para  = []  :: list(), 'GlossSeeAlso'  = []  :: list()}).
-record('49933946', {'ID'  = []  :: list(), 'SortAs'  = []  :: list(), 'GlossTerm'  = []  :: list(), 'Acronym'  = []  :: list(), 'Abbrev'  = []  :: list(), 'GlossDef'  = '111785629':new()  :: '111785629':'111785629'(), 'GlossSee'  = []  :: list()}).
-record('131402670', {'GlossEntry'  = '49933946':new()  :: '49933946':'49933946'()}).
-record('6257036', {title  = []  :: list(), 'GlossList'  = '131402670':new()  :: '131402670':'131402670'()}).
-record('34707836', {title  = []  :: list(), 'GlossDiv'  = '6257036':new()  :: '6257036':'6257036'()}).
-record('22207878', {glossary  = '34707836':new()  :: '34707836':'34707836'()}).

Now edit a sample module :

-module(test).

-include("/tmp/records.hrl").

-export([test/1]).

test(File) -> A = jason:decode_file(File, [{mode, record}]),
              io:format("~p~n", [A#'22207878'.glossary#'34707836'.'GlossDiv'#'6257036'.'GlossList'#'131402670'.'GlossEntry'#'49933946'.'GlossTerm']).

Compile and test module :

1> c(test).
{ok,test}
2> test:test("git/jason/priv/ex1.json").
"Standard Generalized Markup Language"
ok

Renaming record definition

Dynamic name of argonaut modules are hard to remember. If JSON structure is stable, we can rename records for simpler names and tell jason to use thoses.

First let's rename records in record definition (using dummy a,b,c,etc.. names for this example, but meaningful names can be used obviously)

JSON to records translation when source is not stable

Let use a JSON source giving temperature of some cities, coming from third party, from an HTTP API for instance :

weather.json

[
 { "city" : "Paris" ,
   "temperature" : 15.6,
   "unit" : "celcius"
 },
 { "city" : "Berlin" ,
   "temperature" : 13.6 ,
   "unit" : "celcius"
 },
 { "city" : "London" ,
   "temperature" : 12.3 ,
   "unit" : "celcius"
 }
]

This API is announced to be possibly changing, by adding some other informations. Using records in Erlang would be a problem if those ones have to be declared in code. Use of jason and some coding precaution solve this problem :

-module(test).

-export([test/1]).

test(File) -> A = jason:decode_file(File, [{mode, record}]),
              lists:foreach(fun(R) -> Argonaut = element(1, R), 
                                      io:format("~w ~s~n", [Argonaut:temperature(R), 
                                                            Argonaut:unit(R)]) 
                            end, A).

But what if JSON change, by adding a new field in records ? Nothing.

weather1.json

[
 { "city" : "Paris" ,
   "temperature" : 15.6,
   "unit" : "celcius",
   "EEC" : true 
 },
 { "city" : "Berlin" ,
   "temperature" : 13.6 ,
   "unit" : "celcius",
   "EEC" : true 
 },
 { "city" : "London" ,
   "temperature" : 12.3 ,
   "unit" : "celcius",
   "EEC" : false
 }
]
1> c(test).
{ok,test}
2> test:test("/tmp/weather.json").
15.6 celcius
13.6 celcius
12.3 celcius
ok
3> test:test("/tmp/weather1.json").
15.6 celcius
13.6 celcius
12.3 celcius
ok

Jason create an argonaut module for each new JSON structure, and this argonaut module can be used dynamically in the code. Obviously, other precautions can be done by checking if temperature/1 function is existing in argonaut module. If not the case, mean that JSON source is invalid or changed too much...

Clone this wiki locally