summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2023-02-12 22:46:48 -0500
committerRobby Zambito <contact@robbyzambito.me>2023-02-12 22:46:48 -0500
commitb1294088059fe22d1a05d0f9637fdd598795d8ea (patch)
tree2031c4c455d3e26c4ab985eae678de7abc1a0042
parent91adcf023b0c2684991161661032e1aae3cd6b0c (diff)
Add json-object-contains-key?, json-list-length, and json-key-not-found.
Update README accordingly and with add examples.
-rw-r--r--.gitignore4
-rw-r--r--README.org96
-rw-r--r--VERSION1
-rw-r--r--lib/zambyte/meta/180.scm31
-rw-r--r--lib/zambyte/meta/chibi.scm15
-rw-r--r--lib/zambyte/meta/gauche.scm24
-rw-r--r--lib/zambyte/meta/gerbil.scm16
-rw-r--r--lib/zambyte/meta/guile.scm14
-rw-r--r--lib/zambyte/meta/json.sld18
-rw-r--r--lib/zambyte/meta/macduffie.scm14
-rw-r--r--lib/zambyte/meta/sagittarius.scm35
11 files changed, 204 insertions, 64 deletions
diff --git a/.gitignore b/.gitignore
index 75d491d..14fea66 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-**/*~ \ No newline at end of file
+**/*~
+README.html
+*.tgz \ No newline at end of file
diff --git a/README.org b/README.org
index 169e103..1c18542 100644
--- a/README.org
+++ b/README.org
@@ -15,51 +15,137 @@ This library aims to be an implementation of the latter which you can just plug
* API
** Constructors
~(json-object pairs ...)~:
+
Constructs a new JSON object.
-pairs are ~pair?~ objects with a ~string?~ as the ~car~, and a ~json-value?~ as the ~cdr~.
+~pairs~ are ~pair?~ objects with a ~string?~ 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.
+~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 ~string?~, and the behavior when ~obj~ does not contain ~key~ is currently undefined.
+~key~ should be a ~string?~.
+
+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~
+
+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 ~string?~, 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 ~string?~ and the ~cdr~ is the associated ~json-value?~.
-~(json-object->list lst)~:
+~(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
+ (define-syntax case-values
+ (syntax-rules ()
+ ((_ vals (pattern body1 body2 ...) ...)
+ (call-with-values (lambda () vals) (case-lambda (pattern body1 body2 ...) ...)))))
+
+ (case-values (json-ref (json-object `("x" . ,(json-list "hello" "world"))) "x")
+ (() 'not-found)
+ ((x) (json-list? x))) ; => #t
+
+ (case-values (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.
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..afaf360
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.0.0 \ No newline at end of file
diff --git a/lib/zambyte/meta/180.scm b/lib/zambyte/meta/180.scm
index 735a895..71ee1a8 100644
--- a/lib/zambyte/meta/180.scm
+++ b/lib/zambyte/meta/180.scm
@@ -2,17 +2,6 @@
(srfi 1)
(srfi 2))
(begin
- (define (string->json str)
- (call-with-port (open-input-string str)
- (lambda (port)
- (json-read port))))
-
- (define (json->string json)
- (call-with-port (open-output-string)
- (lambda (port)
- (json-write json port)
- (get-output-string port))))
-
(define (json-object . pairs)
(map
(lambda (pair)
@@ -25,11 +14,27 @@
(define json-list? vector?)
;; json-null? already defined in srfi 180
+ (define (json-object-contains-key? obj key)
+ (and (assoc (string->symbol key) obj) #t))
+
+ (define (string->json str)
+ (call-with-port (open-input-string str)
+ (lambda (port)
+ (json-read port))))
+
+ (define (json->string json)
+ (call-with-port (open-output-string)
+ (lambda (port)
+ (json-write json port)
+ (get-output-string port))))
+
(define (json-object-ref json key)
- (and-let* ((pair (assoc (string->symbol key) json)))
- (cdr pair)))
+ (or (and-let* ((pair (assoc (string->symbol key) json)))
+ (cdr pair))
+ ((json-key-not-found))))
(define json-list-ref vector-ref)
+ (define json-list-length vector-length)
(define (json-object->alist json)
(map
diff --git a/lib/zambyte/meta/chibi.scm b/lib/zambyte/meta/chibi.scm
index 49f72f6..fc8e942 100644
--- a/lib/zambyte/meta/chibi.scm
+++ b/lib/zambyte/meta/chibi.scm
@@ -2,9 +2,6 @@
(srfi 1)
(srfi 2))
(begin
- ;; json->string already defined in chibi json
- ;; string->json already defined in chibi json
-
(define (json-object . pairs)
(map
(lambda (pair)
@@ -16,14 +13,22 @@
(define json-object? list?)
(define json-list? vector?)
+ (define (json-object-contains-key? obj key)
+ (and (assoc (string->symbol key) obj) #t))
+
(define (json-null? obj)
(eq? obj json-null))
+ ;; json->string already defined in chibi json
+ ;; string->json already defined in chibi json
+
(define (json-object-ref json key)
- (and-let* ((pair (assoc (string->symbol key) json)))
- (cdr pair)))
+ (or (and-let* ((pair (assoc (string->symbol key) json)))
+ (cdr pair))
+ ((json-key-not-found))))
(define json-list-ref vector-ref)
+ (define json-list-length vector-length)
(define (json-object->alist json)
(map
diff --git a/lib/zambyte/meta/gauche.scm b/lib/zambyte/meta/gauche.scm
index 733599a..3ab2062 100644
--- a/lib/zambyte/meta/gauche.scm
+++ b/lib/zambyte/meta/gauche.scm
@@ -2,6 +2,18 @@
(rfc json)
(srfi 1))
(begin
+ (define json-object list)
+ (define json-list vector)
+ (define json-null 'null)
+ (define json-object? list?)
+ (define json-list? vector?)
+
+ (define (json-null? obj)
+ (eq? obj json-null))
+
+ (define (json-object-contains-key? obj key)
+ (and (assoc key obj) #t))
+
(define array-handler list->vector)
(define object-handler identity)
(define (special-handler x)
@@ -17,16 +29,12 @@
(parse-json-string str)))
(define json->string construct-json-string)
- (define json-object list)
- (define json-list vector)
- (define json-null 'null)
- (define json-object? list?)
- (define json-list? vector?)
- (define (json-null? obj)
- (eq? obj json-null))
+ (define (json-object-ref json key)
+ (or (assoc-ref json key)
+ ((json-key-not-found))))
- (define json-object-ref assoc-ref)
(define json-list-ref vector-ref)
+ (define json-list-length vector-length)
(define json-object->alist identity)
(define json-list->list vector->list))
diff --git a/lib/zambyte/meta/gerbil.scm b/lib/zambyte/meta/gerbil.scm
index 00f7b0e..8d545ef 100644
--- a/lib/zambyte/meta/gerbil.scm
+++ b/lib/zambyte/meta/gerbil.scm
@@ -1,23 +1,29 @@
(import (std text json)
(scheme hash-table))
(begin
- (define string->json string->json-object)
- (define json->string json-object->string)
-
(define (json-object . pairs)
(alist->hash-table pairs equal?))
(define json-list list)
- (define json-null #!void)
+ (define json-null (if #f #f))
(define json-object? hash-table?)
(define json-list? list?)
(define (json-null? obj)
(eq? obj json-null))
+ (define (json-object-contains-key? json key)
+ (hash-table-contains? json key))
+
+ (define string->json string->json-object)
+ (define json->string json-object->string)
+
(define (json-object-ref json key)
- (hash-table-ref json (string->symbol key)))
+ (or (and (json-object-contains-key? json key)
+ (hash-table-ref json key))
+ ((json-key-not-found))))
(define json-list-ref list-ref)
+ (define json-list-length length)
(define json-object->alist hash-table->alist)
(define json-list->list values))
diff --git a/lib/zambyte/meta/guile.scm b/lib/zambyte/meta/guile.scm
index cbd998b..96968d6 100644
--- a/lib/zambyte/meta/guile.scm
+++ b/lib/zambyte/meta/guile.scm
@@ -2,8 +2,6 @@
(srfi 1)
(srfi 2))
(begin
- (define string->json json-string->scm)
- (define json->string scm->json-string)
(define json-object list)
(define json-list vector)
(define json-null 'null)
@@ -13,10 +11,18 @@
(define (json-null? obj)
(eq? obj json-null))
+ (define (json-object-cointains-key? obj key)
+ (and (assoc key obj) #t))
+
+ (define string->json json-string->scm)
+ (define json->string scm->json-string)
+
(define (json-object-ref json key)
- (and-let* ((pair (assoc key json)))
- (cdr pair)))
+ (or (and-let* ((pair (assoc key json)))
+ (cdr pair))
+ ((json-key-not-found))))
(define json-list-ref vector-ref)
+ (define json-list-length vector-length)
(define json-object->alist values)
(define json-list->list vector->list))
diff --git a/lib/zambyte/meta/json.sld b/lib/zambyte/meta/json.sld
index 0313516..58479e8 100644
--- a/lib/zambyte/meta/json.sld
+++ b/lib/zambyte/meta/json.sld
@@ -1,21 +1,25 @@
(define-library (zambyte meta json)
;; portable
(export json-ref
- json-value?)
- ;; non-portable
- (export string->json
- json->string
+ json-value?
- json-object
+ json-key-not-found)
+ ;; non-portable
+ (export json-object
json-list
json-null
json-object?
json-list?
json-null?
+ json-object-contains-key?
+
+ string->json
+ json->string
json-object-ref
json-list-ref
+ json-list-length
json-object->alist
json-list->list)
@@ -36,7 +40,9 @@
(string? obj)
(json-null? obj)
(json-list? obj)
- (json-object? obj))))
+ (json-object? obj)))
+
+ (define json-key-not-found (make-parameter (lambda () (values)))))
;; non-portable
(cond-expand
((and (library (macduffie json)) (srfi 69))
diff --git a/lib/zambyte/meta/macduffie.scm b/lib/zambyte/meta/macduffie.scm
index f80ea18..8a42183 100644
--- a/lib/zambyte/meta/macduffie.scm
+++ b/lib/zambyte/meta/macduffie.scm
@@ -2,9 +2,6 @@
(json-null md:json-null))
(srfi 69))
(begin
- (define string->json json-read-string)
- (define json->string json-write-string)
-
(define (json-object . pairs)
(alist->hash-table pairs))
@@ -13,7 +10,16 @@
(define json-object? hash-table?)
(define json-list? list?)
;; json-null? already defined in macduffie json
- (define json-object-ref hash-table-ref)
+ (define json-object-contains-key? hash-table-exists?)
+ (define string->json json-read-string)
+ (define json->string json-write-string)
+
+ (define (json-object-ref json key)
+ (or (and (hash-table-exists? json key)
+ (hash-table-ref json key))
+ ((json-key-not-found))))
+
(define json-list-ref list-ref)
+ (define json-list-length length)
(define json-object->alist hash-table->alist)
(define json-list->list values))
diff --git a/lib/zambyte/meta/sagittarius.scm b/lib/zambyte/meta/sagittarius.scm
index 3b5a741..97deb0b 100644
--- a/lib/zambyte/meta/sagittarius.scm
+++ b/lib/zambyte/meta/sagittarius.scm
@@ -2,17 +2,6 @@
(srfi 1)
(srfi 2))
(begin
- (define (string->json str)
- (call-with-port (open-input-string str)
- (lambda (port)
- (json-read port))))
-
- (define (json->string json)
- (call-with-port (open-output-string)
- (lambda (port)
- (json-write json port)
- (get-output-string port))))
-
(define (json-object . pairs)
(if (eq? (*json-map-type*) 'vector)
(apply vector pairs)
@@ -38,13 +27,33 @@
(define (json-null? obj)
(eq? obj json-null))
+ (define (json-object-contains-key? obj key)
+ (and (assoc key (json-object->alist obj)) #t))
+
+ (define (string->json str)
+ (call-with-port (open-input-string str)
+ (lambda (port)
+ (json-read port))))
+
+ (define (json->string json)
+ (call-with-port (open-output-string)
+ (lambda (port)
+ (json-write json port)
+ (get-output-string port))))
+
(define (json-object-ref json key)
- (and-let* ((pair (assoc key (json-object->alist json))))
- (cdr pair)))
+ (or (and-let* ((pair (assoc key (json-object->alist json))))
+ (cdr pair))
+ ((json-key-not-found))))
(define (json-list-ref json index)
(list-ref (json-list->list json) index))
+ (define (json-list-length json)
+ (if (eq? (*json-map-type*) 'vector)
+ (length json)
+ (vector-length json)))
+
(define (json-object->alist json)
(if (eq? (*json-map-type*) 'vector)
(vector->list json)