From 497f36b02e1056bafcb181a0d10fac7e3268130c Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Mon, 12 Jun 2023 00:22:30 -0400 Subject: Return the mutated object from record mutators. Update README --- README.org | 67 +++++++++++++++++++++++++++++++++++++---------- lib/zambyte/meta/json.sld | 3 ++- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/README.org b/README.org index d61b0e8..44e9836 100644 --- a/README.org +++ b/README.org @@ -1,46 +1,87 @@ #+TITLE: JSON meta library * What is a meta library? -The purpose of this library is to be a portable shim for many JSON libraries. +The purpose of this library is to provide a high level abstraction layer for handling JSON. * 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. +- Use (possibly by writing) 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. +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 +** Values +~json-null~: + +This is a constant value which represents null in JSON. ** 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~. +~pairs~ must satisfy ~pair?~, with a ~car~ that satisfies ~symbol?~, and a ~cdr~ that satisfies ~json-value?~. +It is an error to construct a ~json-object~ that contains duplicate keys. 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~ must satisfy ~json-value?~. A list can be converted to a JSON list like so: ~(apply json-list some-list)~ -~json-null~: +*** Syntax +~json~: + +Constructs a new JSON value. +The ~json~ macro has ~list~ and ~object~, ~null~, ~true~, and ~false~ keywords, and handles quoting the appropriate terms. + +*Example*: + +#+begin_src scheme + (json (object + (x . 2) + (y . (list "hello" 1 true null (object (a . (object))))))) +#+end_src -This is not a constructor, but instead it is a value which represents null in JSON. +~define-json-record-type~: + +Creates a new record-type with an additional procedure definition that will convert a string to an instance of the record. +Objects that were not constructed via a record constructor, but that have at least all of the keys required to construct the record, may be transparently treated as instances of the record-type. + +*Example*: + +#+begin_src scheme + (define-json-record-type + (point x y) + string->point + point? + (x point->x) + (y point->y set-y!)) + + (define a (point 1 2)) + (define b (json (object (x . 3) (y . 4)))) + (define c (string-point "{\"x\": 5, \"y\": 6}")) + + (and (point? a) (point? b) (point? c)) ; => #t + (eq? 3 (point->x b)) ; => #t + (set-y! a 5) + (set-y! b 5) + (eq? (point->y a) (point->y b)) ; => #t +#+end_src ** 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. +This is true for values returned by the [[Constructors][constructors]], ~json-null~, 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. +Either the result of deserializing a string formatted as a JSON object, the ~json-object~ constructor, or a constructor created as the result of a ~define-json-record-type~ expression. ~(json-list? obj)~: @@ -49,7 +90,7 @@ Either the result of deserializing a string formatted as a JSON list, or from th ~(json-null? obj)~: -Returns true if ~obj~ is ~eq?~ to ~json-null~. +Returns true if ~obj~ is ~json-null~. ~(json-object-contains-key? obj key)~: @@ -70,11 +111,11 @@ Returns the ~json-value?~ associated with ~key~ in ~obj~. 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)~. +The default behavior of ~json-key-not-found~ will return nothing to its continuation. ~(json-list-ref lst i)~: -Returns the ~json-value?~ at index ~i~. +Returns the ~json-value?~ at index ~i~ of ~lst~. ~(json-list-length lst)~: @@ -89,8 +130,6 @@ If ~json~ is a ~json-list?~ and ~ref~ is a ~number?~, get the element at that in 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)~: diff --git a/lib/zambyte/meta/json.sld b/lib/zambyte/meta/json.sld index 0802f94..32ce22c 100644 --- a/lib/zambyte/meta/json.sld +++ b/lib/zambyte/meta/json.sld @@ -133,7 +133,8 @@ (if (json-record? json) (or (and-let* ((pair (assoc 'name (json-record->mutators json))) (mut! (cdr pair))) - (mut! (json-record->internal-record json) value)) + (mut! (json-record->internal-record json) value) + json) (error (string-append (symbol->string 'mutator) ": no mutator for field") (json-record->name json) 'name)) (json-object-set! json 'name value))) (define-accessors-and-mutators rest :::))))) -- cgit