1# jsx (v2.9.0) # 2 3 4an erlang application for consuming, producing and manipulating [json][json]. 5inspired by [yajl][yajl] 6 7**jsx** is built via [rebar3][rebar3], [rebar][rebar] or [mix][mix] and continuous integration testing provided courtesy [travis-ci][travis] 8 9current status: [![Build Status](https://secure.travis-ci.org/talentdeficit/jsx.png?branch=develop)](http://travis-ci.org/talentdeficit/jsx) 10 11**jsx** is released under the terms of the [MIT][MIT] license 12 13copyright 2010-2016 alisdair sullivan 14 15## really important note ## 16 17there are a few changes for users upgrading from 1.x. see [CHANGES.md](CHANGES.md) 18for the overview or [migrating from 1.x](#migrating) for the details 19 20 21## index ## 22 23* [quickstart](#quickstart) 24* [description](#description) 25 - [migrating from 1.x](#migrating) 26 - [json <-> erlang mapping](#json---erlang-mapping) 27 - [incomplete input](#incomplete-input) 28* [data types](#data-types) 29 - [`json_term()`](#json_term) 30 - [`json_text()`](#json_text) 31 - [`event()`](#event) 32 - [`option()`](#option) 33* [exports](#exports) 34 - [`encoder/3`, `decoder/3` & `parser/3`](#encoder3-decoder3--parser3) 35 - [`decode/1,2`](#decode12) 36 - [`encode/1,2`](#encode12) 37 - [`format/1,2`](#format12) 38 - [`minify/1`](#minify1) 39 - [`prettify/1`](#prettify1) 40 - [`is_json/1,2`](#is_json12) 41 - [`is_term/1,2`](#is_term12) 42 - [`maps_support/0`](#maps_support0) 43* [callback exports](#callback_exports) 44 - [`Module:init/1`](#moduleinit1) 45 - [`Module:handle_event/2`](#modulehandle_event2) 46* [acknowledgements](#acknowledgements) 47 48 49## quickstart ## 50 51#### to add to a rebar3 project #### 52Add to `rebar.config` 53```erlang 54... 55{erl_opts, [debug_info]}. 56{deps, [ 57 ... 58 {jsx, {git, "https://github.com/talentdeficit/jsx.git", {branch, "v2.8.0"}}} 59]}. 60... 61``` 62 63#### to build the library and run tests #### 64 65```bash 66$ rebar3 compile 67$ rebar3 eunit 68$ rebar compile 69$ rebar eunit 70$ mix compile 71$ mix eunit 72``` 73 74#### to convert a utf8 binary containing a json string into an erlang term #### 75 76```erlang 771> jsx:decode(<<"{\"library\": \"jsx\", \"awesome\": true}">>). 78[{<<"library">>,<<"jsx">>},{<<"awesome">>,true}] 792> jsx:decode(<<"{\"library\": \"jsx\", \"awesome\": true}">>, [return_maps]). 80#{<<"awesome">> => true,<<"library">> => <<"jsx">>} 813> jsx:decode(<<"[\"a\",\"list\",\"of\",\"words\"]">>). 82[<<"a">>, <<"list">>, <<"of">>, <<"words">>] 83``` 84 85#### to convert an erlang term into a utf8 binary containing a json string #### 86 87```erlang 881> jsx:encode([{<<"library">>,<<"jsx">>},{<<"awesome">>,true}]). 89<<"{\"library\": \"jsx\", \"awesome\": true}">> 902> jsx:encode(#{<<"library">> => <<"jsx">>, <<"awesome">> => true}). 91<<"{\"awesome\":true,\"library\":\"jsx\"}">> 923> jsx:encode([<<"a">>, <<"list">>, <<"of">>, <<"words">>]). 93<<"[\"a\",\"list\",\"of\",\"words\"]">> 94``` 95 96#### to check if a binary or a term is valid json #### 97 98```erlang 991> jsx:is_json(<<"[\"this is json\"]">>). 100true 1012> jsx:is_json("[\"this is not\"]"). 102false 1033> jsx:is_term([<<"this is a term">>]). 104true 1054> jsx:is_term([this, is, not]). 106false 107``` 108 109#### to minify some json #### 110 111```erlang 1121> jsx:minify(<<"{ 113 \"a list\": [ 114 1, 115 2, 116 3 117 ] 118}">>). 119<<"{\"a list\":[1,2,3]}">> 120``` 121 122#### to prettify some json #### 123 124```erlang 1251> jsx:prettify(<<"{\"a list\":[1,2,3]}">>). 126<<"{ 127 \"a list\": [ 128 1, 129 2, 130 3 131 ] 132}">> 133``` 134 135#### to compile **jsx** so that it always decodes json objects to maps #### 136 137```bash 138$ JSX_FORCE_MAPS rebar3 compile 139$ JSX_FORCE_MAPS mix compile 140``` 141 142## description ## 143 144 145**jsx** is an erlang application for consuming, producing and manipulating 146[json][json] 147 148**jsx** follows the json [spec][rfc4627] as closely as possible with allowances for 149real world usage 150 151**jsx** is pragmatic. the json spec allows extensions so **jsx** extends the spec in a 152number of ways. see the section on `strict` in [options](#option) below though 153 154json has no official comments but this parser allows c/c++ style comments. 155anywhere whitespace is allowed you can insert comments (both `// ...` and `/* ... */`) 156 157some particularly irresponsible json emitters leave trailing commas at the end of 158objects or arrays. **jsx** allows a single trailing comma in input. multiple commas 159in any posistion or a preceding comma are still errors 160 161all **jsx** decoder input should be `utf8` encoded binaries. sometimes you get binaries 162that are almost but not quite valid utf8 whether due to improper escaping or poor 163encoding. **jsx** replaces invalid codepoints and poorly formed sequences with the 164unicode replacement character (`u+FFFD`) but does it's best to return something 165comprehensible 166 167json only allows keys and strings to be delimited by double quotes (`u+0022`) but 168javascript allows them to be delimited by single quotes (`u+0027`) as well. **jsx** 169follows javascript in this. strings that start with single quotes can contain double 170quotes but must end with single quotes and must escape any single quotes they contain 171 172json and **jsx** only recognize escape sequences as outlined in the json spec. it just 173ignores bad escape sequences leaving them in strings unaltered 174 175 176### migrating from 1.x ### 177 178if you're migrating from jsx v1.x to v2.x in most cases you won't need to 179make any changes to your code 180 181support for otp 17.0's new map type is now enabled by default when compiling 182via rebar for any release that supports them. jsx should still compile cleanly for 183earlier releases without any user intervention 184 185if you used any of `replaced_bad_utf8`, `single_quoted_strings`, `comments`, 186`ignored_bad_escapes` or `relax` you can simply omit them from your calls to jsx, 187they are all enabled by default now. if you want stricter parsing see the new 188[`strict` options](#option) available 189 190if you were using jsx to parse partial json using it's streaming features it is now 191disabled by default. you'll need to pass the `stream` option to calls to jsx functions 192to reenable it 193 194support for `pre_encode` and `post_decode` has been removed. they were fragile and hard 195to understand and they prevented evolution of the encoding and decoding code 196 197 198### json <-> erlang mapping ### 199 200**json** | **erlang** 201--------------------------------|-------------------------------- 202`number` | `integer()` and `float()` 203`string` | `binary()` and `atom()` 204`true`, `false` and `null` | `true`, `false` and `null` 205`array` | `[]` and `[JSON]` 206`object` | `#{}`, `[{}]` and `[{binary() OR atom() OR integer(), JSON}]` 207see below | `datetime()` 208 209* numbers 210 211 javascript and thus json represent all numeric values with floats. there's no 212 reason for erlang -- a language that supports arbitrarily large integers -- to 213 restrict all numbers to the ieee754 range 214 215 whenever possible, **jsx** will interpret json numbers that look like integers as 216 integers. other numbers will be converted to erlang's floating point type, which 217 is nearly but not quite iee754. negative zero is not representable in erlang (zero 218 is unsigned in erlang and `0` is equivalent to `-0`) and will be interpreted as 219 regular zero. numbers not representable are beyond the concern of this implementation, 220 and will result in parsing errors 221 222 when converting from erlang to json, floats are represented with their 223 shortest representation that will round trip without loss of precision. this 224 means that some floats may be superficially dissimilar (although 225 functionally equivalent). for example, `1.0000000000000001` will be 226 represented by `1.0` 227 228* strings 229 230 json strings must be unicode encoded binaries or erlang atoms. in practice, 231 because **jsx** only accepts `utf8` binaries all binary strings must be `utf8`. 232 in addition to being unicode json strings restrict a number of codepoints and 233 define a number of escape sequences 234 235 json string escapes of the form `\uXXXX` will be converted to their 236 equivalent codepoints during parsing. this means control characters and 237 other codepoints disallowed by the json spec may be encountered in resulting 238 strings. the utf8 restriction means the surrogates are explicitly disallowed. 239 if a string contains escaped surrogates (`u+d800` to `u+dfff`) they are 240 interpreted but only when they form valid surrogate pairs. surrogates 241 encountered otherwise are replaced with the replacement codepoint (`u+fffd`) 242 243 all erlang strings are represented by **valid** `utf8` encoded binaries. the 244 encoder will check strings for conformance. badly formed `utf8` sequences may 245 be replaced with the replacement codepoint (`u+fffd`) according to the unicode 246 spec 247 248 this implementation performs no normalization on strings beyond that 249 detailed here. be careful when comparing strings as equivalent strings 250 may have different `utf8` encodings 251 252* true, false and null 253 254 the json primitives `true`, `false` and `null` are represented by the 255 erlang atoms `true`, `false` and `null`. surprise 256 257* arrays 258 259 json arrays are represented with erlang lists of json values as described 260 in this section 261 262* objects 263 264 json objects are represented by erlang proplists. json maps may also be 265 encoded to json and optionally decoded to maps (via the `return_maps` 266 option) 267 268 the empty object has the special representation `[{}]` to differentiate it 269 from the empty list. ambiguities like `[true, false]` prevent the use of 270 the shorthand form of property lists using atoms as properties so all 271 properties must be tuples. all keys must be encoded as in `string` or as 272 atoms or integers (which will be escaped and converted to binaries for 273 presentation to handlers). values should be valid json values. repeated 274 keys are tolerated in json text decoded to erlang terms but are not allowed 275 in erlang terms encoded to json 276 277* datetime 278 279 erlang datetime tuples (`{{Year, Month, Day}, {Hour, Min, Sec}}`) as returned 280 from `erlang:localtime/0` are automatically encoded as [iso8601][iso8601] 281 strings and are assumed to be UTC time. no conversion is attempted of json [iso8601][iso8601] strings in decoded json 282 283 284### incomplete input ### 285 286**jsx** can handle incomplete json texts. if the option `stream` is passed to the decoder 287or parser and if a partial json text is parsed, rather than returning a term from 288your callback handler, **jsx** returns `{incomplete, F}` where `F` is a function with 289an identical API to the anonymous fun returned from `decoder/3`, `encoder/3` or 290`parser/3`. it retains the internal state of the parser at the point where input 291was exhausted. this allows you to parse as you stream json over a socket or file 292descriptor, or to parse large json texts without needing to keep them entirely in 293memory 294 295however, it is important to recognize that **jsx** is conservative by default. **jsx** will 296not consider the parsing complete even when input is exhausted and the json text is 297unambiguously incomplete. to end parsing call the `incomplete` function with the 298argument `end_stream` (or `end_json`) like: 299 300```erlang 3011> {incomplete, F} = jsx:decode(<<"[">>, [stream]). 302{incomplete,#Fun<jsx_decoder.1.122947756>} 3032> F(end_stream). % can also be `F(end_json)` 304** exception error: bad argument 3053> {incomplete, G} = F(<<"]">>). 306{incomplete,#Fun<jsx_decoder.1.122947756>} 3074> G(end_stream). % can also be `G(end_json)` 308[] 309``` 310 311 312## data types ## 313 314#### `json_term()` #### 315 316```erlang 317json_term() = [json_term()] 318 | [{binary() | atom() | integer(), json_term()}] 319 | #{} % map of any size, not just the empty map 320 | true 321 | false 322 | null 323 | integer() 324 | float() 325 | binary() 326 | atom() 327 | datetime() 328``` 329 330the erlang representation of json. binaries should be `utf8` encoded, or close 331at least 332 333#### `json_text()` #### 334 335```erlang 336json_text() = binary() 337``` 338 339a utf8 encoded binary containing a json string 340 341#### `event()` #### 342 343```erlang 344event() = start_object 345 | end_object 346 | start_array 347 | end_array 348 | {key, binary()} 349 | {string, binary()} 350 | {integer, integer()} 351 | {float, float()} 352 | {literal, true} 353 | {literal, false} 354 | {literal, null} 355 | end_json 356``` 357 358the subset of [`token()`](#token) emitted by the decoder and encoder to handlers 359 360#### `option()` #### 361 362```erlang 363option() = dirty_strings 364 | escaped_forward_slashes 365 | escaped_strings 366 | repeat_keys 367 | stream 368 | strict 369 | {strict, [strict_option()]} 370 | return_tail 371 | uescape 372 | unescaped_jsonp 373 374strict_option() = comments 375 | trailing_commas 376 | utf8 377 | single_quotes 378 | escapes 379``` 380 381**jsx** functions all take a common set of options. not all flags have meaning 382in all contexts, but they are always valid options. functions may have 383additional options beyond these. see 384[individual function documentation](#exports) for details 385 386- `dirty_strings` 387 388 json escaping is lossy; it mutates the json string and repeated application 389 can result in unwanted behaviour. if your strings are already escaped (or 390 you'd like to force invalid strings into "json" you monster) use this flag 391 to bypass escaping. this can also be used to read in **really** invalid json 392 strings. everything between unescaped quotes are passed as is to the resulting 393 string term. note that this takes precedence over any other options 394 395- `escaped_forward_slashes` 396 397 json strings are escaped according to the json spec. this means forward 398 slashes (solidus) are only escaped when this flag is present. otherwise they 399 are left unescaped. you may want to use this if you are embedding json 400 directly into a html or xml document 401 402- `escaped_strings` 403 404 by default both the encoder and decoder return strings as utf8 binaries 405 appropriate for use in erlang. escape sequences that were present in decoded 406 terms are converted into the appropriate codepoint while encoded terms are 407 unaltered. this flag escapes strings as if for output in json, removing 408 control codes and problematic codepoints and replacing them with the 409 appropriate escapes 410 411- `stream` 412 413 see [incomplete input](#incomplete-input) 414 415- `strict` 416 417 as mentioned [earlier](#description), **jsx** is pragmatic. if you're more of a 418 json purist or you're really into bdsm stricter adherence to the spec is 419 possible. the following restrictions are available 420 421 * `comments` 422 423 comments are disabled and result in a `badarg` error 424 425 * `trailing_commas` 426 427 trailing commas in an object or list result in `badarg` errors 428 429 * `utf8` 430 431 invalid codepoints and malformed unicode result in `badarg` errors 432 433 * `single_quotes` 434 435 only keys and strings delimited by double quotes (`u+0022`) are allowed. the 436 single quote (`u+0027`) results in a `badarg` error 437 438 * `escapes` 439 440 escape sequences not adhering to the json spec result in a `badarg` error 441 442 * `control_codes` 443 444 control codes in strings result in `badarg` errors 445 446 any combination of these can be passed to **jsx** by using `{strict, [strict_option()]}`. 447 `strict` is equivalent to `{strict, [comments, trailing_commas, utf8, single_quotes, escapes, control_codes]}` 448 449- `return_tail` 450 451 upon reaching the end of a valid json term in an input stream return the term and any 452 remaining bytes in the input stream as `{with_tail, term(), binary()}` where the second 453 member of the tuple is the json term and the third is any remaining bytes. note that 454 leading whitespace will be stripped from the tail 455 456- `uescape` 457 458 escape all codepoints outside the ascii range for 7 bit clean output. note 459 this escaping takes place even if no other string escaping is requested (via 460 `escaped_strings`) 461 462- `unescaped_jsonp` 463 464 javascript interpreters treat the codepoints `u+2028` and `u+2029` as 465 significant whitespace. json strings that contain either of these codepoints 466 will be parsed incorrectly by some javascript interpreters. by default, 467 these codepoints are escaped (to `\u2028` and `\u2029`, respectively) to 468 retain compatibility. this option simply removes that escaping 469 470 471## exports ## 472 473 474#### `encoder/3`, `decoder/3` & `parser/3` #### 475 476```erlang 477decoder(Module, Args, Opts) -> Fun((JSONText) -> any()) 478encoder(Module, Args, Opts) -> Fun((JSONTerm) -> any()) 479parser(Module, Args, Opts) -> Fun((Tokens) -> any()) 480 481 Module = atom() 482 Args = any() 483 Opts = [option()] 484 JSONText = json_text() 485 JSONTerm = json_term() 486 Tokens = event() | [event()] 487``` 488 489**jsx** is a json compiler with interleaved tokenizing, syntactic analysis and 490semantic analysis stages. included are two tokenizers; one that handles json 491texts (`decoder/3`) and one that handles erlang terms (`encoder/3`). there is 492also an entry point to the syntactic analysis stage for use with user-defined 493tokenizers (`parser/3`) 494 495all three functions return an anonymous function that takes the appropriate type 496of input and returns the result of performing semantic analysis, the tuple 497`{incomplete, F}` where `F` is a new anonymous function (see 498[incomplete input](#incomplete_input)) or a `badarg` error exception if 499syntactic analysis fails 500 501`Module` is the name of the callback module 502 503`Args` is any term that will be passed to `Module:init/1` prior to syntactic 504analysis to produce an initial state 505 506`Opts` are detailed [here](#option) 507 508check out [callback module documentation](#callback_exports) for details of 509the callback module interface 510 511#### `decode/1,2` #### 512 513```erlang 514decode(JSON) -> Term 515decode(JSON, Opts) -> Term 516 517 JSON = json_text() 518 Term = json_term() 519 Opts = [option() | labels | {labels, Label} | return_maps] 520 Label = binary | atom | existing_atom | attempt_atom 521 F = fun((any()) -> any()) 522``` 523 524`decode` parses a json text (a `utf8` encoded binary) and produces an erlang 525term 526 527the option `labels` controls how keys are converted from json to 528erlang terms. `binary` (the default behavior) does no conversion 529beyond normal escaping. `atom` converts keys to erlang atoms and 530results in a `badarg` error if the keys fall outside the range of erlang 531atoms. `existing_atom` is identical to `atom` except it will not add 532new atoms to the atom table and will result in a `badarg` error if the atom 533does not exist. `attempt_atom` will convert keys to atoms when they exist, 534and leave them as binary otherwise 535 536the option `return_maps` will attempt to return objects as maps instead of 537proplists. this option has no effect when used with releases that do not 538support maps 539 540raises a `badarg` error exception if input is not valid json 541 542 543#### `encode/1,2` #### 544 545```erlang 546encode(Term) -> JSON 547encode(Term, Opts) -> JSON 548 549 Term = json_term() 550 JSON = json_text() 551 Opts = [option() | space | {space, N} | indent | {indent, N}] 552 N = pos_integer() 553``` 554 555`encode` converts an erlang term into json text (a `utf8` encoded binary) 556 557the option `{space, N}` inserts `N` spaces after every comma and colon in your 558json output. `space` is an alias for `{space, 1}`. the default is `{space, 0}` 559 560the option `{indent, N}` inserts a newline and `N` spaces for each level of 561indentation in your json output. note that this overrides spaces inserted after 562a comma. `indent` is an alias for `{indent, 1}`. the default is `{indent, 0}` 563 564raises a `badarg` error exception if input is not a valid 565[erlang representation of json](#json---erlang-mapping) 566 567 568#### `format/1,2` #### 569 570```erlang 571format(JSON) -> JSON 572format(JSON, Opts) -> JSON 573 574 JSON = json_text() 575 Opts = [option() | space | {space, N} | indent | {indent, N}] 576 N = pos_integer() 577``` 578 579`format` parses a json text (a `utf8` encoded binary) and produces a new json 580text according to the format rules specified by `Opts` 581 582the option `{space, N}` inserts `N` spaces after every comma and colon in your 583json output. `space` is an alias for `{space, 1}`. the default is `{space, 0}` 584 585the option `{indent, N}` inserts a newline and `N` spaces for each level of 586indentation in your json output. note that this overrides spaces inserted after 587a comma. `indent` is an alias for `{indent, 1}`. the default is `{indent, 0}` 588 589raises a `badarg` error exception if input is not valid json 590 591 592#### `minify/1` #### 593 594```erlang 595minify(JSON) -> JSON 596 597 JSON = json_text() 598``` 599 600`minify` parses a json text (a `utf8` encoded binary) and produces a new json 601text stripped of whitespace 602 603raises a `badarg` error exception if input is not valid json 604 605 606#### `prettify/1` #### 607 608```erlang 609prettify(JSON) -> JSON 610 611 JSON = json_text() 612``` 613 614`prettify` parses a json text (a `utf8` encoded binary) and produces a new json 615text equivalent to `format(JSON, [{space, 1}, {indent, 2}])` 616 617raises a `badarg` error exception if input is not valid json 618 619 620#### `is_json/1,2` #### 621 622```erlang 623is_json(MaybeJSON) -> true | false 624is_json(MaybeJSON, Opts) -> true | false 625 626 MaybeJSON = any() 627 Opts = options() 628``` 629 630returns true if input is a valid json text, false if not 631 632what exactly constitutes valid json may be [altered](#option) 633 634 635#### `is_term/1,2` #### 636 637```erlang 638is_term(MaybeJSON) -> true | false 639is_term(MaybeJSON, Opts) -> true | false 640 641 MaybeJSON = any() 642 Opts = options() 643``` 644 645returns true if input is a valid erlang representation of json, false if not 646 647what exactly constitutes valid json may be altered via [options](#option) 648 649 650#### `maps_support/0` #### 651 652```erlang 653maps_support() -> true | false 654``` 655 656if **jsx** was compiled with map support enabled returns `true`, else 657`false` 658 659 660## callback exports ## 661 662the following functions should be exported from a **jsx** callback module 663 664#### `Module:init/1` #### 665 666```erlang 667Module:init(Args) -> InitialState 668 669 Args = any() 670 InitialState = any() 671``` 672 673whenever any of `encoder/3`, `decoder/3` or `parser/3` are called, this function 674is called with the `Args` argument provided in the calling function to obtain 675`InitialState` 676 677#### `Module:handle_event/2` #### 678 679```erlang 680Module:handle_event(Event, State) -> NewState 681 682 Event = [event()] 683 State = any() 684 NewState = any() 685``` 686 687semantic analysis is performed by repeatedly calling `handle_event/2` with a 688stream of events emitted by the tokenizer and the current state. the new state 689returned is used as the input to the next call to `handle_event/2`. the 690following events must be handled: 691 692- `start_object` 693 694 the start of a json object 695 696- `end_object` 697 698 the end of a json object 699 700- `start_array` 701 702 the start of a json array 703 704- `end_array` 705 706 the end of a json array 707 708- `{string, binary()}` 709 710 a json string. it will usually be a `utf8` encoded binary. see the 711 [options](#option) for possible exceptions. note that keys are also 712 json strings 713 714- `{integer, integer()}` 715 716 an erlang integer (bignum) 717 718- `{float, float()}` 719 720 an erlang float 721 722- `{literal, true}` 723 724 the atom `true` 725 726- `{literal, false}` 727 728 the atom `false` 729 730- `{literal, null}` 731 732 the atom `null` 733 734- `end_json` 735 736 this event is emitted when syntactic analysis is completed. you should 737 do any cleanup and return the result of your semantic analysis 738 739 740## acknowledgements ## 741 742jsx wouldn't be what it is without the contributions of [Paul J. Davis](https://github.com/davisp), [Lloyd Hilaiel](https://github.com/lloyd), [John Engelhart](https://github.com/johnezang), [Bob Ippolito](https://github.com/etrepum), [Brujo Benavides](https://github.com/elbrujohalcon), [Alex Kropivny](https://github.com/amtal), [Steve Strong](https://github.com/srstrong), [Michael Truog](https://github.com/okeuday), [Devin Torres](https://github.com/devinus), [fogfish](https://github.com/fogfish), [emptytea](https://github.com/emptytea), [John Daily](https://github.com/macintux), [Ola Bäckström](https://github.com/olabackstrom), [Joseph Crowe](https://github.com/JosephCrowe), [Patrick Gombert](https://github.com/patrickgombert), [Eshengazin S. Kuat](https://github.com/eskuat), [Max Lapshin](https://github.com/maxlapshin), [Bikram Chatterjee](https://github.com/c-bik), [Michael Uvarov](https://github.com/arcusfelis), [Led](https://github.com/Ledest) and [tvv](https://github.com/tvv) 743 744[json]: http://json.org 745[yajl]: http://lloyd.github.com/yajl 746[MIT]: http://www.opensource.org/licenses/mit-license.html 747[rebar3]: https://rebar3.org 748[rebar]: https://github.com/rebar/rebar 749[mix]: http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html 750[meck]: https://github.com/eproxus/meck 751[rfc4627]: http://tools.ietf.org/html/rfc4627 752[travis]: https://travis-ci.org/ 753[jsxn]: https://github.com/talentdeficit/jsxn 754[iso8601]: http://www.iso.org/iso/iso8601 755