jsond
#lang jsond | package: jsond |
This package provides a convienient format to embed JSON data in racket programs by making the JSON data (surprise!) racket programs.
1 Quick Start
Suppose, for example, we had some JSON data consisting of a list of albums and singles.
["Cycles", "Flatspin", "Long Way to Climb"] |
We also have a map of user favorites (each value is an index in the albums array).
{ |
"Jonathan Gordon": 0, |
"Brad Rubinstein": 2, |
"Paul Willmott": 1, |
"Jason Hall": 0, |
"Adam Rich": 1 |
} |
Normally, we would need to require the json library and use read-json to read these data files. With jsond, however, we can make the files into a program:
#lang jsond #:name albums ["Cycles", "Flatspin", "Long Way to Climb"] #:name favorites { "Jonathan Gordon": 0, "Brad Rubinstein": 2, "Paul Willmott": 1, "Jason Hall": 0, "Adam Rich": 1 }
If we put this in a file lisp.rkt, we suddenly have a program!
> (require "lisp.rkt") > albums '("Cycles" "Flatspin" "Long Way to Climb")
> favorites
'#hasheq((|Adam Rich| . 1)
(|Brad Rubinstein| . 2)
(|Jason Hall| . 0)
(|Jonathan Gordon| . 0)
(|Paul Willmott| . 1))
> (for/hash ([(member fav-id) (in-hash favorites)]) (values member (list-ref albums fav-id)))
'#hash((|Adam Rich| . "Flatspin")
(|Brad Rubinstein| . "Long Way to Climb")
(|Jason Hall| . "Cycles")
(|Jonathan Gordon| . "Cycles")
(|Paul Willmott| . "Flatspin"))
The program can also be run to recover the original JSON. The following racket code is equivalent to running a command-line
# racket lisp.rkt |
> (require (submod "lisp.rkt" main)) {"albums":["Cycles","Flatspin","Long Way to Climb"],"favorites":{"Adam Rich":1,"Brad Rubinstein":2,"Jason Hall":0,"Jonathan Gordon":0,"Paul Willmott":1}}
The jsond language supports all of the JSON specification in JSON values, as well as regular racket comments between value definitions:
#lang jsond |
#:name abc "abc" |
;; comment |
#:name num 123 |
#:name array [1, 2, {"xyz": "abc"}, true, false, null] |
> (require jsond/examples/data) > abc "abc"
> num 123
> array '(1 2 #hasheq((xyz . "abc")) #t #f null)
2 Syntax
| ‹jsond› | ::= | ‹name-json›* |
| ‹name-json› | ::= | #:name ‹id› ‹json› |
There may be any style of racket comment between ‹name-json›s. Each use of #:name, ‹id›, and ‹json› must be whitespace-separated. ‹json› can be any valid JSON value as determined by read-json. ‹id› can be any valid Racket identifier.
3 Semantics
The jsond language produces a module that provides each of the ‹id›s as a binding to the jsexpr? corresponding to the adjacent ‹json›.
The module has a submodule main that, when run, calls write-json on a hash mapping each provided ‹id› to its value.