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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
#+TITLE: JSON meta library
* What is a meta library?
The purpose of this library is to be a portable shim for many JSON libraries.
* Why?
If one wants to write portable Scheme which does some JSON processing, one must either:
- Abandon hope of being portable, and depend on an implementation specific library.
- Use a portable JSON library which is redundant, and may conflict with other libraries that expect parsed JSON to be represented in a certain way.
- Write a bunch of cond-expands to act as a portability layer, and use different JSON libraries in different contexts.
This library aims to be an implementation of the latter which you can just plug in as a dependency, instead of writing your own.
* API
** Constructors
~(json-object pairs ...)~:
Constructs a new JSON object.
~pairs~ are ~pair?~ objects with a ~symbol?~ as the ~car~, and a ~json-value?~ as the ~cdr~.
An alist can be converted to a JSON object like so: ~(apply json-object alist)~
~(json-list objs ...)~:
Constructs a new JSON list.
~objs~ are ~json-value?~ objects.
A list can be converted to a JSON list like so: ~(apply json-list some-list)~
~json-null~:
This is not a constructor, but instead it is a value which represents null in JSON.
** Predicates
~(json-value? obj)~:
Returns true if ~obj~ is a value that can be serialized as JSON.
This is true for values related to the constructors, and for numbers, strings, and booleans.
~(json-object? obj)~:
Returns true if ~obj~ is a value that can be serialized as a JSON object.
Either the result of deserializing a string formatted as a JSON object, or from the ~json-object~ constructor.
~(json-list? obj)~:
Returns true if ~obj~ is a value that can be serialized as a JSON list.
Either the result of deserializing a string formatted as a JSON list, or from the ~json-list~ constructor.
~(json-null? obj)~:
Returns true if ~obj~ is ~eq?~ to ~json-null~.
~(json-object-contains-key? obj key)~:
Returns true if ~obj~ contains the ~key~.
** Serialization
~(json->string obj)~:
Convert a ~json-value?~ to a JSON formatted ~string?~.
~(string->json str)~
Converts a ~string?~ into a ~json-value?~
** Selectors
~(json-object-ref obj key)~:
Returns the ~json-value?~ associated with ~key~ in ~obj~.
~key~ should be a ~symbol?~.
The behavior when ~key~ is not found in ~obj~ can be controlled with the ~json-key-not-found~ parameter.
The value of ~json-key-not-found~ should be a procedure of no arguments, and the return value of the procedure is returned, if any exists.
The default behavior of ~json-key-not-found~ will return nothing, using ~(values)~.
~(json-list-ref lst i)~:
Returns the ~json-value?~ at index ~i~.
~(json-list-length lst)~:
Returns the length of ~lst~.
~(json-ref json ref refs ...)~:
General JSON reference accessor.
If ~json~ is a ~json-list?~ and ~ref~ is a ~number?~, get the element at that index of the list.
If ~json~ is a ~json-object?~ and ~ref~ is a ~symbol?~, get the value associated with that key in the object.
If there are more ~refs ...~, they are recursively applied.
** Conversion
~(json-object->alist obj)~:
Convert ~obj~ to a ~list?~ of ~pair?~ where the ~car~ of each pair is a ~symbol?~ and the ~cdr~ is the associated ~json-value?~.
~(json-list->list lst)~:
Convert ~lst~ to a ~list?~ of ~json-value?~.
** Examples
#+begin_src scheme
(json-list->list (apply json-list lst)) ; => lst
#+end_src
#+begin_src scheme
(json-object->alist (apply json-object alist)) ; => alist
#+end_src
#+begin_src scheme
(json-null? (string->json "null")) ; => #t
#+end_src
#+begin_src scheme
(json-object-contains-key?
(json-object '(a . 5)
`(b . ,(json-list 1 2 3)))
'a) ; => #t
(json-object-contains-key?
(json-object '(a . 5)
`(b . ,(json-list 1 2 3)))
'c) ; => #f
#+end_src
#+begin_src scheme
(json-ref
(json-object `(x . ,(json-list "hello" "world")))
'x
0) ; => "hello"
#+end_src
#+begin_src scheme
(import (srfi 210))
(case-receive (json-ref (json-object `("x" . ,(json-list "hello" "world"))) "x")
(() 'not-found)
((x) (json-list? x))) ; => #t
(case-receive (json-ref (json-object `("x" . ,(json-list "hello" "world"))) "y")
(() 'not-found)
((x) (json-list? x))) ; => not-found
#+end_src
* Feedback
Please email me at: contact (at) robbyzambito (dot) me if you have any suggestions or would like for me to add support for another JSON library.
|