JSON: Writing Output
July 15, 2011
Writing output is much easier than parsing input, because you don’t have to worry that something is invalid. Here’s our solution:
(define (write-json val . args)
(let ((port (if (pair? args) (car args) (current-output-port))))
(define (write-value val)
(cond ((json-null? val) (display " null" port))
((boolean? val) (display (if val " true" " false") port))
((number? val) (display " ") (display (number->string val) port))
((string? val) (display " " port) (write val port))
((vector? val) (if (zero? (vector-length val)) (display " []" port)
(begin (display " [") (write-value (vector-ref val 0))
(do ((i 1 (+ i 1))) ((= i (vector-length val)))
(display " ," port) (write-value (vector-ref val i)))
(display " ]" port))))
((pair? val) (if (zero? (length val)) (display " {}" port)
(begin (display " {" port) (write-value (caar val))
(display " :" port) (write-value (cdar val))
(do ((val (cdr val) (cdr val))) ((null? val))
(display " ," port) (write-value (caar val))
(display " :" port) (write-value (cdar val)))
(display " }" port))))
(else (error 'write-json "unrecognized"))))
(write-value val)))
The function is recursive because JSON objects can be recursive. We also provide a version of the function that writes to a string instead of a port:
(define (json->string obj)
(with-output-to-string (lambda () (write-json obj))))
You can see the entire JSON library, both input and output, assembled at http://programmingpraxis.codepad.org/mPIKEbNN.