# (chibi json)

A library for reading and writing data in JSON format (RFC 8259).

#### `(json-read [in])`

Reads a JSON expression from port `in`. Objects are represented as alists with symbol keys, arrays as Scheme vectors, null as the symbol `'null`, and strings, numbers and booleans as the corresponding Scheme types.

#### `(string->json str)`

Returns the JSON representation of `str` as from `json-read`.

      (string->json "{\"mean\": 2.2, \"quartiles\": [1, 2, 3, 4]}")

`=> ((mean . 2.2) (quartiles . #(1 2 3 4)))`

#### `(json-write json [out])`

Writes a JSON representation of `obj` to port `out`, where `obj` should follow the same mappings as in `json-read`.

#### `(json->string json)`

Returns the string representation of `json` as from `json-write`.

#### `(make-json-reader spec [strict?])`

Returns a procedure of one argument, an input port, which reads a JSON object according to the specification `spec`, which can be one of:

- a record type: reads a json object with field names corresponding to the record names
- a predicate: reads an arbitrary json object, and returns that object if the predicate succeeds, or an error otherwise
- a vector of one element: reads a json array of objects as described by the vector element
- a list: the car should be a record type, and the cdr an alist of (field-name . spec). The spec can be a symbol, in which case it is the record field name (allowing aliasing), otherwise it is a normal spec to read and set the corresponding field

If `strict?` is specified and true, raises an error if any unknown field names are specified in an object.

Examples:

    (begin
     (define-record-type Employee
       (make-employee name id title department)
       employee?
       (name employee-name)
       (id employee-id)
       (title employee-title)
       (department employee-department))
     (define-record-type Team
       (make-team name lead devs)
       team?
       (name team-name)
       (lead team-lead)
       (devs team-devs))
     (define read-team
       (make-json-reader
        `(,Team
          (lead . ,Employee)
          (name . ,string?)
          (devs . #(,Employee)))))
     (define team
      (read-team
       (open-input-string
        "{\"name\": \"A-Team\",
          \"lead\": {\"name\": \"Hannibal\", \"id\": 321},
          \"devs\": [{\"name\": \"B.A.\", \"id\": 7},
                     {\"name\": \"Murdock\", \"id\": 13}]}")))
     (cons (team-name team)
           (map employee-name
                (cons (team-lead team) (vector->list (team-devs team))))))

    ERROR on line 26 of file lib/srfi/9.scm: immutable binding: Employee