-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathoneline.rkt
105 lines (93 loc) · 3.47 KB
/
oneline.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#lang racket/base
(require (only-in (file "./json.rkt")
count-properties
object-properties
property-value))
(require (only-in racket/port
with-output-to-string))
(require (only-in racket/list
take
last
rest
first
empty?))
(require (only-in racket/string
string-split
string-trim))
(require json)
(module+ test
(require rackunit))
(define (json-in-one-line js)
(unless (jsexpr? js)
(error "Not a jsexpr? value."))
(cond ((eq? 'null js)
"null")
((real? js)
(format "~a" js))
((boolean? js)
(if js "true" "false"))
((string? js)
(format "~s" js))
((list? js)
(let ([num-items (length js)]
[items js])
(if (= num-items 0)
"[]"
(with-output-to-string
(lambda ()
(display "[")
;; all elements except the final one
(for ([item (take items (- num-items 1))])
(display (json-in-one-line item))
(display ","))
;; last item
(display (json-in-one-line (last items)))
(display "]"))))))
((hash? js)
(let ([num-props (count-properties js)])
(if (= num-props 0)
"{}"
(with-output-to-string
(lambda ()
(display "{")
(let ([props (object-properties js)])
;; all but final property
(for ([prop (take props (- num-props 1))])
(display (format "\"~s\":" prop))
(display (json-in-one-line (property-value js prop)))
(display ","))
(let ([final (last props)])
(display (format "\"~s\":" final))
(display (json-in-one-line (property-value js final)))))
(display "}"))))))
(else
(error "Unhandled JSON data:" js))))
(provide json-in-one-line)
(module+ test
(check-equal? (json-in-one-line 'null)
"null")
(check-equal? (json-in-one-line -5)
"-5")
(check-equal? (json-in-one-line "hello!")
"\"hello!\"")
(check-equal? (json-in-one-line #f)
"false")
(check-equal? (json-in-one-line (list))
"[]")
(check-equal? (json-in-one-line (make-string 1 #\nul))
"\"\\u0000\"")
(check-equal? (json-in-one-line "üff då phô")
"\"üff då phô\"")
(check-equal? (json-in-one-line (hasheq))
"{}")
(check-equal? (json-in-one-line (list #t "jim bob" (list)))
"[true,\"jim bob\",[]]")
(let ([obj (hasheq 'some "pig" 'pig 'null)])
(let ([rendered (json-in-one-line obj)])
(check-true (or (string=? rendered "{\"some\":\"pig\",\"pig\":null}")
(string=? rendered "{\"pig\":null,\"some\":\"pig\"}")) rendered)))
(let ([doc (hasheq 'dependencies (hasheq 'foo (list "bar")))])
(check-equal? (json-in-one-line doc)
"{\"dependencies\":{\"foo\":[\"bar\"]}}"))
(check-equal? (json-in-one-line (list 5 (list #t) 'null))
"[5,[true],null]"))