README.md

# ljson

[![Build Status][travis badge]][travis]
[![LFE Versions][lfe badge]][lfe]
[![Erlang Versions][erlang badge]][versions]
[![Tags][github tags badge]][github tags]
[![Downloads][hex downloads]][hex package]

*An LFE library which provides a unified JSON experience*

[![Project Logo][logo]][logo-large]


#### Contents

* [Introduction](#introduction-)
* [Dependencies](#dependencies-)
* [Installation](#installation-)
* [Usage](#usage-)
* [Future](#future-)
* [License](#license-)


## Introduction [↟](#contents)

This library was educated by
[Chiron](http://en.wikipedia.org/wiki/Chiron#Students)
to avenge the crimes against JSON and its heirs in the Erlang world. It is
destined to search for the
[Golden Macro](http://en.wikipedia.org/wiki/Golden_Fleece), as
revealed by the
[Cloud Goddess](http://en.wikipedia.org/wiki/Nephele).


## Dependencies [↟](#contents)

As of version 0.4.0, this project assumes that you have
[rebar3](https://github.com/rebar/rebar3) installed somwhere in your `$PATH`.
It no longer uses the old version of rebar. If you do not wish to use rebar3,
you may use the most recent rebar2-compatible release of ljson: 0.3.1.


## Installation [↟](#contents)

Just add it to your `rebar.config` deps:

```erlang
{deps, [
  ...
  {ljson, {git, "git@github.com:lfex/ljson.git", "master"}}
    ]}.
```

And then do the usual:

```bash
$ make compile
```


## Usage [↟](#contents)

The following usage examples are all done from the LFE REPL:

```
$ make repl-no-deps
Starting an LFE REPL ...
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] ...

LFE Shell V6.2 (abort with ^G)
>
```


Encode simple LFE data to JSON:

```cl
> (ljson:encode 'a)
#"\"a\""
ok
> (ljson:encode "a")
#"[97]"
ok
> (ljson:encode 1)
#"1"
ok
> (ljson:encode 3.14)
#"3.14"
ok
> (ljson:encode '(a b c 42))
#"[\"a\",\"b\",\"c\",42]"
ok
> (ljson:encode #(a b))
#"{\"a\":\"b\"}"
ok
> (ljson:encode '(#(a b) #(c d)))
#"{\"a\":\"b\",\"c\":\"d\"}"
ok
>
```


Decode simple JSON:

```cl
> (ljson:decode #b("\"a\""))
#"a"
ok
> (ljson:decode "\"a\""))
#"a"
ok
> (ljson:decode #b("[97]"))
"a"
ok
> (ljson:decode #b("1"))
1
ok
> (ljson:decode #b("3.14"))
3.14
ok
> (ljson:decode #b("[\"a\",\"b\",\"c\",42]"))
(#"a" #"b" #"c" 42)
ok
> (ljson:decode "{\"a\": \"b\"}")
#(#"a" #"b")
ok
> (ljson:decode "{\"a\":\"b\",\"c\":\"d\"}")
(#(#"a" #"b") #(#"c" #"d"))
ok
> (ljson:decode
    #B(123 34 97 34 58 34 98 34 44 34 99 34 58 34 100 34 125))
(#(#"a" #"b") #(#"c" #"d"))
ok
```

Decode a JSON data structure (note that, for formatting purposes, the data
below has been presented separated with newlines; this won't work in the
LFE REPL -- you'll need to put it all on one line):

```cl
> (set json-data "{
  \"First Name\": \"Jón\",
  \"Last Name\": \"Þórson\",
  \"Is Alive?\": true,
  \"Age\": 25,
  \"Height_cm\": 167.6,
  \"Address\": {
    \"Street Address\": \"í Gongini 5 Postsmoga 108\",
    \"City\": \"Tórshavn\",
    \"Country\": \"Faroe Islands\",
    \"Postal Code\": \"100\"
  },
  \"Phone Numbers\": [
    {
      \"Type\": \"home\",
      \"Number\": \"20 60 30\"
    },
    {
      \"Type\": \"office\",
      \"Number\": \"+298 20 60 20\"
    }
  ],
  \"Children\": [],
  \"Spouse\": null}")
> (set data (ljson:decode json-data))
(#(#"First Name" #"Jón")
 #(#"Last Name" #"Þórson")
 #(#"Is Alive?" true)
 #(#"Age" 25)
 #(#"Height_cm" 167.6)
 #(#"Address"
   (#(#"Street Address" #"í Gongini 5 Postsmoga 108")
    #(#"City" #"Tórshavn")
    #(#"Country" #"Faroe Islands")
    #(#"Postal Code" #"100")))
 #(#"Phone Numbers"
   ((#(#"Type" #"home") #(#"Number" #"20 60 30"))
    (#(#"Type" #"office") #(#"Number" #"+298 20 60 20"))))
 #(#"Children" ())
 #(#"Spouse" null))
```

Now let's take it full circle by encoding it again:

```cl
> (ljson:prettify (ljson:encode data))
{
  "First Name": "Jón",
  "Last Name": "Þórson",
  "Is Alive?": true,
  "Age": 25,
  "Height_cm": 167.6,
  "Address": {
    "Street Address": "í Gongini 5 Postsmoga 108",
    "City": "Tórshavn",
    "Country": "Faroe Islands",
    "Postal Code": "100"
  },
  "Phone Numbers": [
    {
      "Type": "home",
      "Number": "20 60 30"
    },
    {
      "Type": "office",
      "Number": "+298 20 60 20"
    }
  ],
  "Children": [],
  "Spouse": null
}
ok
```

Let's do the same, but this time from LFE data:

```cl
> (set lfe-data
   `(#(#b("First Name") ,(binary ("Jón" utf8)))
     #(#b("Last Name") ,(binary ("Þórson" utf8)))
     #(#b("Is Alive?") true)
     #(#b("Age") 25)
     #(#b("Height_cm") 167.6)
     #(#b("Address")
      #((#(#b("Street Address") ,(binary ("í Gongini 5 Postsmoga 108" utf8)))
        #(#b("City") ,(binary ("Tórshavn" utf8)))
        #(#b("Country") #b("Faroe Islands"))
        #(#b("Postal Code") #b("100")))))
     #(#b("Phone Numbers")
      (#((#(#b("Type") #b("home")) #(#b("Number") #b("20 60 30"))))
       #((#(#b("Type") #b("office")) #(#b("Number") #b("+298 20 60 20"))))))
     #(#b("Children") ())
     #(#b("Spouse") null)))
(#(#B(...)))
> (ljson:prettify (ljson:encode lfe-data))
{
  "First Name": "Jón",
  "Last Name": "Þórson",
  "Is Alive?": true,
  "Age": 25,
  "Height_cm": 167.6,
  "Address": {
    "Street Address": "í Gongini 5 Postsmoga 108",
    "City": "Tórshavn",
    "Country": "Faroe Islands",
    "Postal Code": "100"
  },
  "Phone Numbers": [
    {
      "Type": "home",
      "Number": "20 60 30"
    },
    {
      "Type": "office",
      "Number": "+298 20 60 20"
    }
  ],
  "Children": [],
  "Spouse": null
}
ok
```


Extract elements from the original converted data structure as well as
our LFE data structure we just entered directly, above:

```cl
> (ljson:get data '("First Name"))
#"Jón"
> (ljson:get data '("Address" "City"))
#"Tórshavn"
> (ljson:get data '("Phone Numbers" 1 "Type"))
#"home"
> (ljson:get lfe-data '("First Name") )
#"Jón"
> (ljson:get lfe-data '("Address" "City")data)
#"Tórshavn"
> (ljson:get lfe-data '("Phone Numbers" 1 "Type"))
#"home"
```

You may also use atom or binary keys:

```cl
> (ljson:get lfe-data '(|Phone Numbers| 1 Number))
#"20 60 30"
> (ljson:get lfe-data '(#"Phone Numbers" 1 #"Number"))
#"20 60 30"
```

Extract elements directly from JSON:

```cl
> (ljson:get json-data '("First Name") #(json))
#"\"J\\u00f3n\""
> (ljson:get json-data '("Address" "City") #(json))
#"\"T\\u00f3rshavn\""
> (ljson:get json-data '("Phone Numbers" 1 "Type") #(json))
#"\"home\""
```


## Under the Deck [↟](#contents)

The Argonauts that are rowing this thing consist of the following:

* mochijson2 - for encoding of nested data
* jsx - for decoding, `prettify` and `minify`
* dict - (wrapped as `pairs`) for large key/value lists
* proplists/lists of tuples - for small key/value lists


## License [↟](#contents)

Apache Version 2 License

Copyright © 2014-2015, Dreki Þórgísl

Copyright © 2015, arpunk

Copyright © 2015-2016, Duncan McGreggor <oubiwann@gmail.com>


<!-- Named page links below: /-->

[logo]: priv/images/jason-argonauts-small.png
[logo-large]: http://dropr.com/coenhamelink/15218/jason_and_the_argonauts/+?p=97582
[org]: https://github.com/lfex
[github]: https://github.com/lfex/ljson
[gitlab]: https://gitlab.com/lfex/ljson
[travis]: https://travis-ci.org/lfex/ljson
[travis badge]: https://img.shields.io/travis/lfex/ljson.svg
[lfe]: https://github.com/rvirding/lfe
[lfe badge]: https://img.shields.io/badge/lfe-1.2.0-blue.svg
[erlang badge]: https://img.shields.io/badge/erlang-R15%20to%2019.1-blue.svg
[versions]: https://github.com/lfex/ljson/blob/master/.travis.yml
[github tags]: https://github.com/lfex/ljson/tags
[github tags badge]: https://img.shields.io/github/tag/lfex/ljson.svg
[github downloads]: https://img.shields.io/github/downloads/lfex/ljson/total.svg
[hex badge]: https://img.shields.io/hexpm/v/ljson.svg?maxAge=2592000
[hex package]: https://hex.pm/packages/ljson
[hex downloads]: https://img.shields.io/hexpm/dt/ljson.svg