Skip to content

Well-typed JSON parser generator inspired by Type Provider

License

Notifications You must be signed in to change notification settings

philnguyen/json-type-provider

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status json-type-provider

This is a library for parsing JSON input into Typed Racket values. By specifying the JSON schema in Typed Racket, the programmer gets a well-typed parser.

Nice things the library provides:

  • No error-handling boilerplate.
  • Flexibility in mapping from JSON format into Racket types. For example, by default, objects are parsed into compact structs that only store fields the programmer cares about. It is also possible to specify a custom conversion that say, convert an object with real and imag directly into Racket's Complex.

Examples

Examples are under test/ directory

  • london_weather.rkt shows a straightforward declaration
  • complex.rkt shows how to convert objects or lists into custom types
  • cards.rkt shows how to impose a more precise type (e.g. enumerations) on raw data

Installation

raco pkg install json-type-provider

Documentation

(There will eventually be Scriblings)

The define-json-types macro will define a type id and generate a parser read-id for each declared id type, whose RHS describes the shape of the data and optionally how it is mapped into a custom Racket type.

(require json-comb)

(define-json-types
  [id desc] ...)

Below is the full grammar:

desc ::= obj-desc | type-desc

type-desc ::= simp-type-desc | (U simp-type-desc ...)

simp-type-desc ::= JSNum
                |  Real
                |  Integer
                |  Float
                |  Boolean
                |  String
                |  #t
                |  #f
                |  'null
                |  id
                |  list-type-desc
                |  (pat => type #:by expr)
                |  ((Listof type-desc) => type #:by-folding expr #:from expr)

list-type-desc ::= (List type-desc ...)
                |  (Listof type-desc)
                |  (List* type-desc ... (Listof type-desc))

pat ::= (List [id : type-desc] ...)
     |  (List* [id : type-desc] ... [id : (Listof type-desc)])
     |  obj-desc
     |  [x : type-desc]

obj-desc ::= (field-desc ... rest-option)

rest-option ::=
             | #:ignore-others
             | #:log-warning-others
             | #:error-others

field-desc ::= [field-name : type-desc]
            |  [field-name : type-desc #:default [expr : type]]


field-name ::= id
            |  (id id)

type = arbitrary Racket type

The libary also provides convenient functions over JSON lists:

;; Parse and fold a JSON list of `X`s into `A` without building an intermediate list
read-fold : (∀ (X A) A (X A → A) (Input-Port → X) → (∀ (B)
                                                      (case->
                                                        [Input-Port → A]
                                                        [Input-Port (Input-Port → B) → (U A B)])))
                                                        
;; Create a sequence of `X` without building an intermediate list
make-sequence-reader : (∀ (X) (Input-Port → X) → Input-Port → (Sequenceof X))

About

Well-typed JSON parser generator inspired by Type Provider

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages