-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjson.rkt
113 lines (94 loc) · 2.79 KB
/
json.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
106
107
108
109
110
111
112
113
#lang racket/base
(provide has-type?
has-property?
property-value
object-properties
object-values
json-non-negative-integer?
remove-property
count-properties)
(require (file "util.rkt")
racket/cmdline
racket/match
racket/contract
racket/list
json)
(module+ test
(require rackunit))
;; constructors
(define/contract (has-property? obj prop)
(hash? (or/c symbol? string?) . -> . boolean?)
(cond ((symbol? prop)
(hash-has-key? obj prop))
((string? prop)
(hash-has-key? obj (string->symbol prop)))))
(module+ test
(let ([obj (hasheq 'foo "bar")])
(check-true (hash? obj))
(check-true (has-property? obj 'foo))
(check-true (has-property? obj "foo"))
(check-false (has-property? obj 'bar))
(check-false (has-property? obj "bar"))))
(define/contract (property-value obj prop)
(hash? (or/c string? symbol?) . -> . jsexpr?)
(cond [(symbol? prop)
(hash-ref obj prop)]
[(string? prop)
(hash-ref obj (string->symbol prop))]))
(define/contract (object-properties obj)
(hash? . -> . (listof symbol?))
(hash-keys obj))
(define/contract (object-values obj)
(hash? . -> . (listof jsexpr?))
(hash-values obj))
(define/contract (json-non-negative-integer? x)
(jsexpr? . -> . boolean?)
(and (integer? x)
(<= 0 x)))
(define/contract (remove-property jsobj prop)
(hash? symbol? . -> . hash?)
(hash-remove jsobj prop))
(define/contract (count-properties js)
(hash? . -> . exact-nonnegative-integer?)
(length (object-properties js)))
(define/contract (has-type? data type)
(jsexpr? (or/c string? (listof string?)) . -> . boolean?)
(match type
[(? list?)
(ormap (lambda (t) (has-type? data t))
type)]
["null"
(eq? 'null data)]
["boolean"
(boolean? data)]
["number"
(number? data)]
["integer"
(integer? data)]
["object"
(hash? data)]
["array"
(list? data)]
["string"
(string? data)]
[else
(error "Unknown JSON data type: " type)]))
;; Command line application for testing whether a file is
;; a JSON file at all
(module+ main
(define json-path
(command-line
#:program "json"
#:args (json-path)
json-path))
(unless (file-exists? json-path)
(complain-and-die (format "Schema file \"~a\" does not exist." json-path)))
(define (parse-fail err) #f)
(define json/bytes (file-content/bytes json-path))
(define json/string (bytes->string json/bytes))
(when (eq? json/string #f)
(complain-and-die (format "Contents of \"~a\" cannot be interpreted as a UTF-8 string." json-path)))
(with-handlers ([exn:fail:read? (lambda (e)
(exit 1))])
(string->jsexpr json/string)
(exit 0)))