Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package guile-json for openSUSE:Factory checked in at 2021-05-13 22:18:44 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/guile-json (Old) and /work/SRC/openSUSE:Factory/.guile-json.new.2988 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "guile-json" Thu May 13 22:18:44 2021 rev:10 rq:892667 version:4.5.2 Changes: -------- --- /work/SRC/openSUSE:Factory/guile-json/guile-json.changes 2020-11-26 23:15:56.229062902 +0100 +++ /work/SRC/openSUSE:Factory/.guile-json.new.2988/guile-json.changes 2021-05-13 22:18:54.395511842 +0200 @@ -1,0 +2,9 @@ +Wed May 12 21:08:03 UTC 2021 - Jonathan Brielmaier <jbrielma...@opensuse.org> + +- Update to 4.5.2: + * Add missing modules to record.scm. + * Allow false values in JSON mappings. + * Introduce (define-json-type) + * Fixed a few parsing issues from JSON Parsing Test Suite + +------------------------------------------------------------------- Old: ---- guile-json-4.4.0.tar.gz guile-json-4.4.0.tar.gz.sig New: ---- guile-json-4.5.2.tar.gz guile-json-4.5.2.tar.gz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ guile-json.spec ++++++ --- /var/tmp/diff_new_pack.TkGe5W/_old 2021-05-13 22:18:54.867510200 +0200 +++ /var/tmp/diff_new_pack.TkGe5W/_new 2021-05-13 22:18:54.871510186 +0200 @@ -1,7 +1,7 @@ # # spec file for package guile-json # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: guile-json -Version: 4.4.0 +Version: 4.5.2 Release: 0 Summary: JSON module for Guile License: GPL-3.0-or-later ++++++ guile-json-4.4.0.tar.gz -> guile-json-4.5.2.tar.gz ++++++ ++++ 1642 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/ChangeLog new/guile-json-4.5.2/ChangeLog --- old/guile-json-4.4.0/ChangeLog 2020-10-22 22:33:09.000000000 +0200 +++ new/guile-json-4.5.2/ChangeLog 2021-02-03 22:14:51.000000000 +0100 @@ -1,3 +1,207 @@ +commit 7cdda5ca9e05fd3f7834c865fe4701f32b885f71 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Wed Feb 3 13:14:20 2021 -0800 + + bump version to 4.5.2 + + NEWS | 5 +++++ + README.md | 2 +- + configure.ac | 2 +- + 3 files changed, 7 insertions(+), 2 deletions(-) + +commit fe1b9ba56a5a29b3338bf6bf1b04a03b95da73c3 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Wed Feb 3 13:12:29 2021 -0800 + + record: add missing modules + + json/record.scm | 2 ++ + 1 file changed, 2 insertions(+) + +commit 8306c6616abf68f24bd4fee65205eb36b96e5f38 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Wed Feb 3 13:12:13 2021 -0800 + + remove pkg-list.scm.in + + Makefile.am | 3 --- + README.md | 3 --- + pkg-list.scm.in | 29 ----------------------------- + 3 files changed, 35 deletions(-) + delete mode 100644 pkg-list.scm.in + +commit 911777ec6c67e927ecb463b30cb9bf6062e9bc6a +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Wed Feb 3 13:09:19 2021 -0800 + + README: fix documentation + + README.md | 31 ++++++++----------------------- + 1 file changed, 8 insertions(+), 23 deletions(-) + +commit f136a8ae9f8976a8e03860b4ba5c25d32c38279f +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Mon Jan 11 09:32:43 2021 -0800 + + bump version to 4.5.1 + + NEWS | 6 ++++++ + README.md | 2 +- + configure.ac | 2 +- + 3 files changed, 8 insertions(+), 2 deletions(-) + +commit 680e4de46ee23d41869446ae7de414c1a4ec27a5 +Merge: 7036482 2a3846b +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Mon Jan 11 09:30:15 2021 -0800 + + Merge pull request #70 from aconchillo/allow-false-values-in-json-mappings + + record: allow false values in json mappings + +commit 2a3846b72174dc76a54b223f418e54f46639b677 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Mon Jan 11 09:21:39 2021 -0800 + + record: allow false values in json mappings + + * json/record.scm (define-json-reader), (define-native-reader): use (assoc) + instead of (assoc-ref) so we can distinguish between false values and fields not + found. This allows us to identify *unspecified* fields versus fields which have + false values. + + Fixes #69 + + json/record.scm | 20 ++++++++++---------- + tests/test-record.scm | 7 +++++-- + 2 files changed, 15 insertions(+), 12 deletions(-) + +commit 7036482c67a6c0b67c1048e981a05270772f9526 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Jan 3 00:38:53 2021 -0800 + + bump version to 4.5.0 + + NEWS | 6 ++++++ + README.md | 2 +- + configure.ac | 4 ++-- + json/record.scm | 2 +- + 4 files changed, 10 insertions(+), 4 deletions(-) + +commit 5143c47a5fcde617846a6d9abd8272b555fcdf95 +Merge: 99e1a4f 17ad5b1 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Jan 3 00:34:29 2021 -0800 + + Merge pull request #68 from aconchillo/json-types + + introduce (define-json-type) + +commit 17ad5b1341e7feded17e6b416db4bb96c52be227 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Jan 3 00:23:54 2021 -0800 + + introduce (define-json-type) + + README.md | 162 +++++++++++++++++++++++++++++++------------------- + json/record.scm | 104 ++++++++++++++++++++++++++------ + tests/test-record.scm | 53 ++++++++++++++++- + 3 files changed, 238 insertions(+), 81 deletions(-) + +commit 99e1a4faf3abbf13243a0d7f27c8ed14112bee8c +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Nov 29 00:21:40 2020 -0800 + + README: use https for download link + + README.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 4b1f8149a3e8b08020c65b4a98fc3bc1f7e30ada +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Nov 29 00:13:35 2020 -0800 + + bump version to 4.4.1 + + NEWS | 7 +++++++ + README.md | 2 +- + configure.ac | 2 +- + 3 files changed, 9 insertions(+), 2 deletions(-) + +commit fba6ce46fdecb97a118c476cd209e4a9a37b08cc +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Nov 29 00:11:19 2020 -0800 + + README: fix markdown + + README.md | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit cc4b012577ffe7e4a1c1867e825275f8344b1745 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sun Nov 29 00:09:01 2020 -0800 + + README: update to markdown + + README | 2 +- + README.org => README.md | 229 ++++++++++++++++++++++++++---------------------- + 2 files changed, 127 insertions(+), 104 deletions(-) + rename README.org => README.md (52%) + +commit d22ca1e2da34561a118623eea22adf22999a9acd +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sat Nov 28 23:50:31 2020 -0800 + + parser: improve array parsing + + Fixes #67 + + json/parser.scm | 44 +++++++++++++++++++++++--------------------- + tests/test-parser.scm | 2 ++ + 2 files changed, 25 insertions(+), 21 deletions(-) + +commit 04c009f725522d649111baa2a52131dd53d59a97 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sat Nov 28 23:50:06 2020 -0800 + + parser: limit exponents to 1000 + + Fixes #67 + + json/parser.scm | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +commit ba167eb775c45bcfb904dbbcb158a2ba90d88dad +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Sat Nov 28 23:49:54 2020 -0800 + + parser: unescaped control characters are not allowed + + Fixes #67 + + json/parser.scm | 5 +++++ + 1 file changed, 5 insertions(+) + +commit 89e2ce975064baf4f434de4d97e54aac704769a0 +Merge: c19851f 656de15 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Thu Oct 22 13:36:58 2020 -0700 + + Merge pull request #66 from aconchillo/release-4.4.0 + + bump version to 4.4.0 + +commit 656de159a9afa552d48a7ffe7adb61c76a5e1388 +Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> +Date: Thu Oct 22 13:34:46 2020 -0700 + + bump version to 4.4.0 + + NEWS | 2 +- + README.org | 2 +- + configure.ac | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + commit c19851f9d2a2e658e7e8272d0d2fc200a5f546cd Merge: 90b60b9 627fd12 Author: Aleix Conchillo Flaqu?? <aconchi...@gmail.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/Makefile.am new/guile-json-4.5.2/Makefile.am --- old/guile-json-4.4.0/Makefile.am 2020-04-08 09:14:06.000000000 +0200 +++ new/guile-json-4.5.2/Makefile.am 2021-02-03 22:11:51.000000000 +0100 @@ -27,9 +27,6 @@ dist-hook: $(SHELL) $(top_srcdir)/ChangeLog > $(top_distdir)/ChangeLog - cp $(top_srcdir)/pkg-list.scm.in $(top_distdir)/pkg-list.scm - # '' is to make OS X happy - sed -i '' "s/%VERSION%/$(PKG_LIST_VERSION)/g" $(top_distdir)/pkg-list.scm GOBJECTS = $(SOURCES:%.scm=%.go) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/NEWS new/guile-json-4.5.2/NEWS --- old/guile-json-4.4.0/NEWS 2020-10-22 22:32:16.000000000 +0200 +++ new/guile-json-4.5.2/NEWS 2021-02-03 22:13:22.000000000 +0100 @@ -1,4 +1,28 @@ +* Version 4.5.2 (Feb 3, 2021) + + - Add missing modules to record.scm. + + +* Version 4.5.1 (Jan 11, 2020) + + - Allow false values in JSON mappings. + (Fixes #70) + + +* Version 4.5.0 (Jan 3, 2020) + + - Introduce (define-json-type) a much simpler way to define JSON objects and + record mappings. It makes use of the existing (define-json-mapping). + + +* Version 4.4.1 (Nov 29, 2020) + + - Fixed a few parsing issues from JSON Parsing Test Suite + (https://github.com/nst/JSONTestSuite). + (Fixes #67) + + * Version 4.4.0 (Oct 22, 2020) - Record-JSON mapping now can define another optional procedure record->scm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/README new/guile-json-4.5.2/README --- old/guile-json-4.4.0/README 2020-10-22 22:31:42.000000000 +0200 +++ new/guile-json-4.5.2/README 2021-02-03 22:13:50.000000000 +0100 @@ -1,5 +1,5 @@ -* guile-json +# guile-json guile-json is a JSON module for Guile. It supports parsing and building JSON documents according to the http://json.org specification. @@ -11,50 +11,47 @@ - Allows JSON pretty printing. -* Installation +# Installation Download the latest tarball and untar it: -- [[http://download.savannah.gnu.org/releases/guile-json/guile-json-4.4.0.tar.gz][guile-json-4.4.0.tar.gz]] +- [guile-json-4.5.2.tar.gz](https://download.savannah.gnu.org/releases/guile-json/guile-json-4.5.2.tar.gz) If you are cloning the repository make sure you run this first: - : $ autoreconf -vif + $ autoreconf -vif Then, run the typical sequence: - : $ ./configure --prefix=<guile-prefix> - : $ make - : $ sudo make install + $ ./configure --prefix=<guile-prefix> + $ make + $ sudo make install Where <guile-prefix> should preferably be the same as your system Guile installation directory (e.g. /usr). If everything installed successfully you should be up and running: - : $ guile - : scheme@(guile-user)> (use-modules (json)) - : scheme@(guile-user)> (scm->json #(1 2 3)) - : [1,2,3] + $ guile + scheme@(guile-user)> (use-modules (json)) + scheme@(guile-user)> (scm->json #(1 2 3)) + [1,2,3] It might be that you installed guile-json somewhere differently than your system's Guile. If so, you need to indicate Guile where to find guile-json, for example: - : $ GUILE_LOAD_PATH=/usr/local/share/guile/site guile + $ GUILE_LOAD_PATH=/usr/local/share/guile/site guile -A pkg-list.scm file is also provided for users of the Guildhall/Dorodango -packaging system. - -* Usage +# Usage guile-json provides a few procedures to parse and build a JSON document. A JSON document is transformed into or from native Guile values according to the following table: | JSON | Guile | -|--------+--------| +|--------|--------| | string | string | | number | number | | object | alist | @@ -64,234 +61,280 @@ | null | 'null | Why are JSON arrays converted to vectors and JSON objects to alists? See this -[[https://lists.gnu.org/archive/html/guile-user/2018-12/msg00039.html][discussion]] +[discussion](https://lists.gnu.org/archive/html/guile-user/2018-12/msg00039.html) for details. By default the value of JSON "null" is mapped to the symbol 'null. However, all guile-json functions allow changing the default null value by specifying the #:null keyword argument with another value. This other value needs to be -recognized by /eq?/. +recognized by *eq?*. To start using guile-json procedures and macros you first need to load the module: - : scheme@(guile-user)> (use-modules (json)) + scheme@(guile-user)> (use-modules (json)) -** Procedures +## Procedures -- *(json->scm #:optional port #:key null)* : Reads a JSON document from the +- (**json->scm** #:optional port #:key null) : Reads a JSON document from the given port, or from the current input port if none is given. Optional arguments: - - /port/ : is optional, it defaults to the current input port. + - *port* : is optional, it defaults to the current input port. Keyword arguments: - - /null/ : value for JSON's null, it defaults to the 'null symbol. + - *null* : value for JSON's null, it defaults to the 'null symbol. -- *(json-string->scm str #:key null)* : Reads a JSON document from the given +- (**json-string->scm** str #:key null) : Reads a JSON document from the given string. Keyword arguments: - - /null/ : value for JSON's null, it defaults to the 'null symbol. + - *null* : value for JSON's null, it defaults to the 'null symbol. -- *(scm->json native #:optional port #:key escape unicode pretty validate null)* : - Creates a JSON document from the given native Guile value. The JSON document - is written into the given port, or to the current output port if non is - given. +- (**scm->json** native #:optional port #:key solidus unicode null validate + pretty) : Creates a JSON document from the given native Guile value. The JSON + document is written into the given port, or to the current output port if non + is given. Optional arguments: - - /port/ : it defaults to the current output port. + - *port* : it defaults to the current output port. Keyword arguments: - - /solidus/ : if true, the slash (/ solidus) character will be escaped + - *solidus* : if true, the slash (/ solidus) character will be escaped (defaults to false). - - /unicode/ : if true, additional to control characters, non-ASCII + - *unicode* : if true, additional to control characters, non-ASCII characters will be escaped as well (defaults to false). - - /null/ : value for JSON's null (defaults to the 'null symbol). + - *null* : value for JSON's null (defaults to the 'null symbol). - - /validate/ : if true, the native value will be validated before starting + - *validate* : if true, the native value will be validated before starting to print the JSON document (defaults to true). - - /pretty/ : if true, the JSON document will be pretty printed (defaults to + - *pretty* : if true, the JSON document will be pretty printed (defaults to false). -- *(scm->json-string native #:key escape unicode pretty validate)* : Creates a - JSON document from the given native Guile value into a string. +- (**scm->json-string** native #:key solidus unicode null validate pretty) : + Creates a JSON document from the given native Guile value into a string. For + keyword arguments meaning see *scm->json*. - Keyword arguments: + Note that when using alists to build JSON objects, symbols or numbers might + be used as keys and they both will be converted to strings. - - /solidus/ : if true, the slash (/ solidus) character will be escaped - (defaults to false). - - /unicode/ : if true, additional to control characters, non-ASCII - characters will be escaped as well (defaults to false). +## Exceptions - - /null/ : value for JSON's null (defaults to the 'null symbol). +A *json-invalid* exception is thrown if an error is found during the JSON +parsing with a single port argument. The line or column where the error +occured can be easily obtained from the port by calling *port-line* or +*port-column*. - - /validate/ : if true, the native value will be validated before starting - to print the JSON document (defaults to true). +When building a JSON document from a native type a *json-invalid* exception +might be thrown with the offending value as an argument (see table above for +supported types). - - /pretty/ : if true, the JSON document will be pretty printed (defaults to - false). - Note that when using alists to build JSON objects, symbols or numbers might - be used as keys and they both will be converted to strings. +## JSON Objects and Records +guile-json 4.5.0 introduces JSON types, a new feature that allows converting +JSON objects into record types and vice versa in a very straight forward +way. This was built on top of *define-json-mapping* which was introduced in +version 4.2.0. -** Exceptions +Let's take a look at an example. Imagine we have the following user account +information: -A /json-invalid/ exception is thrown if an error is found during the JSON -parsing with a single port argument. The line or column where the error -occured can be easily obtained from the port by calling /port-line/ or -/port-column/. +``` +{ + "id": 1234, + "username": "jane" +} +``` -When building a JSON document from a native type a /json-invalid/ exception -might be thrown with the offending value as an argument (see table above for -supported types). +We can easily create a +[record](https://www.gnu.org/software/guile/manual/html_node/Records.html) +representing that data with *define-json-type* by simply doing: +``` +> (define-json-type <account> + (id) + (username)) +``` -** JSON Objects and Records +This will define the record constructor, the predicate and conversion procedures +like *json->account* or *account->json* (see *define-json-type* for more +details). -guile-json 4.2.0 introduces a new feature to allow converting a JSON object -into a record type and vice versa. This feature works very well, for example, -when creating REST APIs. +We can now create a new account and check its contents as with regular records: -- *(define-json-mapping rtd ctor pred json->record [<=> record->json [<=> scm->record <=> record->scm]] - (field getter spec ...) ...)* : - Define a new mapping between a JSON object and a record type, ?? la SRFI-9. +``` +> (define account (make-account "1234" "jane")) +> (account-id account) +"1234" +> (account-username account) +"jane" +``` - - /rtd/ : the name of the record type. +Or we can use the auto-generated *scm->account* to create the account: - - /ctor/ : the name for the record constructor procedure. +``` +> (define account (scm->account '(("id" . "1234") ("username" . "jane")))) +``` - - /pred/ : a predicate procedure to check if a given argument holds a record - of this type. +It is also possible to convert the record to a JSON string: - - /json->record/ : the name of the procedure to convert a JSON object into a - record of this type. +``` +> (account->json account) +"{\"id\":\"1234\",\"username\":\"jane\"}" +``` - - /<=> record->json/ : optional name of the procedure to convert a record of - this type to JSON object. +Or from a JSON string to a new record: - - /<=> scm->record/ : optional name of the procedure to convert an alist - representation of this record into a record of this type. +``` +> (define json-account "{\"id\":\"1234\",\"username\":\"jane\"}") +> (json->account json-account) +#<<account> id: "1234" username: "jane"> +``` - - /<=> record->scm/ : optional name of the procedure to convert a record of - this type to a native alist whose values should be compatible with - guile-json's supported type. This might be used when record fields contain - other records. +### Macros - - /((field getter spec ...) ...)/ : a series of field specifications. +- (**define-json-type** rtd (field key type) ...) : Define a new mapping between + a JSON object and a record type. This will automatically define the record + constructor, the predicate, all field getters and record to/from JSON + conversions. For more control use *define-json-mapping*. - - /field/ : the name of a JSON object field. + - *rtd* : the name of the record type. - - /getter/ : the name of the procedure to get the value of this field - given a record of this type. + - *((field key type) ...)* : a series of field specifications. - - /spec/ : a different name for the field of this JSON object. If given, - this name will be used instead of field. + - *field* : the name of a JSON object field. - - /json->value/ : an optional procedure that will be used to convert the - JSON value to the value contained in the record. + - *key* : a different name for the field of this JSON object. If given, this + name will be used instead of the field name when serializing or + deserializing. - - /value->scm/ : an optional procedure that will be used to convert the - value contained in the record to one of the native Guile values - supported by guile-json. + - *type* : indicates that this field contains a record type. It is also + possible to indicate that the field contains an array of objects of the + same record type by using the vector syntax *#(type)*. -When serializing a record to JSON it is possible to set a field to the -=*unspecified*= value in order to omit it from serialization. +- (**define-json-mapping** rtd ctor pred json->record [<=> record->json [<=> + scm->record]] (field getter key ...) ...) : Define a new mapping between a + JSON object and a record type, ?? la SRFI-9. -*** Example + - *rtd* : the name of the record type. -- A simple example that defines an account type with two fields: /id/ and - /username/: + - *ctor* : the name for the record constructor procedure. - : > (define-json-mapping <account> - : make-account - : account? - : json->account <=> account->json - : (id account-id) - : (username account-username)) + - *pred* : a predicate procedure to check if a given argument holds a record + of this type. -- We can create a new account and check its contents as with regular records: + - *json->record* : the name of the procedure to convert a JSON object, read + from a port, string, or alist, into a record of this type. - : > (define my-account (make-account "11111" "user-one")) - : > (account-id my-account) - : "11111" - : > (account-username my-account) - : "user-one" + - *<=> record->json* : optional name of the procedure to convert a record of + this type to a JSON string. -- Now we can convert it to a JSON object: + - *<=> scm->record* : optional name of the procedure to convert a JSON object, + represented as an alist, into a record of this type. This is equivalent to + *json->record* when an alist is passed. - : > (account->json my-account) - : "{\"id\":\"11111\",\"username\":\"user-one\"}" + - *<=> record->scm* : optional name of the procedure to convert a record of + this type to a JSON objected represented as an alist. -- Or, given a JSON object we can create a new record: + - *((field getter ...) ...)* : a series of field specifications. - : > (define json-account "{\"id\":\"22222\",\"username\":\"user-two\"}") - : > (define my-other-account (json->account json-account)) - : > (account-id my-other-account) - : "22222" - : > (account-username my-other-account) - : "user-two" + - *field* : the name of a JSON object field. + - *getter* : the name of the procedure to get the value of this field + given a record of this type. -** Examples + - *key* : a different name for the field of this JSON object. If given, this + name will be used instead of the field name when serializing or + deserializing. + + - *scm->value* : an optional procedure that will be used to convert native + values supported by guile-json to the value contained in the record. Used + when reading JSON. + + - *value->scm* : an optional procedure that will be used to convert the + value contained in the record to a native value supported by guile-json + Used when writing JSON. + +### Records and null fields + +When serializing a record to JSON it is possible to set a field to the +\*unspecified\* value in order to omit it from serialization. + + +# Examples - Build the string "hello world": - : > (scm->json "hello world") - : "hello world" +``` +> (scm->json "hello world") +"hello world" +``` - Build the [1, 2, 3] array: - : > (scm->json #(1 2 3)) - : [1,2,3] +``` +> (scm->json #(1 2 3)) +[1,2,3] +``` - Build the object { "project" : "foo", "author" : "bar" } using an alist: - : > (scm->json '(("project" . "foo") ("author" . "bar"))) - : {"project":"foo","author":"bar"} +``` +> (scm->json '(("project" . "foo") ("author" . "bar"))) +{"project":"foo","author":"bar"} +``` - Build the same object but this time using symbols: - : > (scm->json '((project . foo) ("author" . "bar"))) - : {"project":"foo","author":"bar"} +``` +> (scm->json '((project . foo) ("author" . "bar"))) +{"project":"foo","author":"bar"} +``` - Build the object { "values" : [ 234, 98.56 ] }: - : > (scm->json '(("values" . #(234 98.56)))) - : {"values":[234,98.56]} +``` +> (scm->json '(("values" . #(234 98.56)))) +{"values":[234,98.56]} +``` - Build the object { "values" : [ 234, 98.56 ] } again, this time using a variable: - : > (define values #(234 98.56)) - : > (scm->json `(("values" . ,values))) - : {"values":[234,98.56]} +``` +> (define values #(234 98.56)) +> (scm->json `(("values" . ,values))) +{"values":[234,98.56]} +``` - Default null value is the 'null symbol: - : > (scm->json 'null) - : null +``` +> (scm->json 'null) +null +``` - The default null value can be changed to something else: - : > (scm->json #nil #:null #nil) - : null - +``` +> (scm->json #nil #:null #nil) +null +``` -* License +# License -Copyright (C) 2013-2020 Aleix Conchillo Flaque <aconchi...@gmail.com> +Copyright (C) 2013-2021 Aleix Conchillo Flaque <aconchi...@gmail.com> guile-json is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/build-aux/test-driver new/guile-json-4.5.2/build-aux/test-driver --- old/guile-json-4.4.0/build-aux/test-driver 2020-10-22 22:32:45.000000000 +0200 +++ new/guile-json-4.5.2/build-aux/test-driver 2021-02-03 22:14:37.000000000 +0100 @@ -42,11 +42,13 @@ { cat <<END Usage: - test-driver --test-name=NAME --log-file=PATH --trs-file=PATH - [--expect-failure={yes|no}] [--color-tests={yes|no}] - [--enable-hard-errors={yes|no}] [--] + test-driver --test-name NAME --log-file PATH --trs-file PATH + [--expect-failure {yes|no}] [--color-tests {yes|no}] + [--enable-hard-errors {yes|no}] [--] TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] + The '--test-name', '--log-file' and '--trs-file' options are mandatory. +See the GNU Automake documentation for information. END } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/configure.ac new/guile-json-4.5.2/configure.ac --- old/guile-json-4.4.0/configure.ac 2020-10-22 22:31:53.000000000 +0200 +++ new/guile-json-4.5.2/configure.ac 2021-02-03 22:13:39.000000000 +0100 @@ -1,7 +1,7 @@ # # configure.ac # -# Copyright (C) 2013-2020 Aleix Conchillo Flaque <aconchi...@gmail.com> +# Copyright (C) 2013-2021 Aleix Conchillo Flaque <aconchi...@gmail.com> # # This file is part of guile-json. # @@ -19,7 +19,7 @@ # along with guile-json. If not, see https://www.gnu.org/licenses/. # -AC_INIT([guile-json], [4.4.0], [aconchi...@gmail.com]) +AC_INIT([guile-json], [4.5.2], [aconchi...@gmail.com]) AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_SRCDIR(json.scm) AC_CONFIG_AUX_DIR([build-aux]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/json/parser.scm new/guile-json-4.5.2/json/parser.scm --- old/guile-json-4.4.0/json/parser.scm 2020-07-23 20:47:22.000000000 +0200 +++ new/guile-json-4.5.2/json/parser.scm 2020-12-07 00:12:28.000000000 +0100 @@ -44,6 +44,9 @@ ((#\sp #\ht #\lf #\cr) #t) (else #f))) +(define (control-char? ch) + (<= (char->integer ch) #x1F)) + (define (skip-whitespaces port) (let ((ch (peek-char port))) (cond @@ -134,7 +137,11 @@ (cond ((or (eqv? ch #\e) (eqv? ch #\E)) (read-char port) - (expt 10 (* (read-sign port) (read-digits port)))) + (let ((sign (read-sign port)) + (digits (read-digits port))) + (if (<= digits 1000) ;; Some maximum exponent. + (expt 10 (* sign digits)) + (json-exception port)))) (else 1)))) (define (read-fraction port) @@ -224,28 +231,30 @@ (define (json-read-array port null) (expect-delimiter port #\[) - (let loop ((values '()) (added #t)) - (skip-whitespaces port) - (let ((ch (peek-char port))) - (cond - ;; Unexpected EOF. - ((eof-object? ch) (json-exception port)) - ;; Handle comma (make sure we added an element). - ((eqv? ch #\,) - (read-char port) + (skip-whitespaces port) + (cond + ;; Special case when array is empty. + ((eqv? (peek-char port) #\]) + (read-char port) + #()) + (else + ;; Read first element in array. + (let loop ((values (list (json-read port null)))) + (skip-whitespaces port) + (let ((ch (peek-char port))) (cond - (added (loop values #f)) - (else (json-exception port)))) - ;; End of array (make sure we added an element). - ((eqv? ch #\]) - (read-char port) - (cond - (added (list->vector (reverse! values))) - (else (json-exception port)))) - ;; This can be any JSON object. - (else - (let ((value (json-read port null))) - (loop (cons value values) #t))))))) + ;; Unexpected EOF. + ((eof-object? ch) (json-exception port)) + ;; Handle comma (if there's a comma there should be another element). + ((eqv? ch #\,) + (read-char port) + (loop (cons (json-read port null) values))) + ;; End of array. + ((eqv? ch #\]) + (read-char port) + (list->vector (reverse! values))) + ;; Anything else other than comma and end of array is wrong. + (else (json-exception port)))))))) ;; ;; String parsing helpers @@ -325,6 +334,8 @@ (cond ;; Unexpected EOF. ((eof-object? ch) (json-exception port)) + ;; Unescaped control characters are not allowed. + ((control-char? ch) (json-exception port)) ;; End of string. ((eqv? ch #\") (reverse-list->string chars)) ;; Escaped characters. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/json/record.scm new/guile-json-4.5.2/json/record.scm --- old/guile-json-4.4.0/json/record.scm 2020-10-22 22:31:04.000000000 +0200 +++ new/guile-json-4.5.2/json/record.scm 2021-02-03 22:04:39.000000000 +0100 @@ -1,6 +1,6 @@ ;;; (json record) --- Guile JSON implementation. -;; Copyright (C) 2020 Aleix Conchillo Flaque <aconchi...@gmail.com> +;; Copyright (C) 2020-2021 Aleix Conchillo Flaque <aconchi...@gmail.com> ;; Copyright (C) 2018, 2019 Ludovic Court??s <l...@gnu.org> ;; ;; This file is part of guile-json. @@ -28,41 +28,44 @@ ;;; Code: (define-module (json record) + #:use-module (json builder) + #:use-module (json parser) #:use-module (srfi srfi-9) - #:export (<=> define-json-mapping)) + #:export (<=> define-json-mapping define-json-type)) (define <=> '<=>) (define-syntax-rule (define-json-reader json->record ctor spec ...) "Define JSON->RECORD as a procedure that converts a JSON representation, -read from a port, string, or hash table, into a record created by CTOR and -following SPEC, a series of field specifications." +read from a port, string, or alist, into a record created by CTOR and following +SPEC, a series of field specifications." (define (json->record input) (let ((table (cond ((port? input) (json->scm input)) ((string? input) (json-string->scm input)) + ;; This allows to pass native values. ((or (null? input) (pair? input)) input)))) (let-syntax ((extract-field (syntax-rules () - ((_ table (field key json->value value->scm)) - (json->value (assoc-ref table key))) - ((_ table (field key json->value)) - (json->value (assoc-ref table key))) + ((_ table (field key scm->value value->scm)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) + ((_ table (field key scm->value)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) ((_ table (field key)) - (assoc-ref table key)) + (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*)) ((_ table (field)) - (assoc-ref table (symbol->string 'field)))))) - (ctor (or (extract-field table spec) *unspecified*) ...))))) + (if (pair? (assoc (symbol->string 'field) table)) (cdr (assoc (symbol->string 'field) table)) *unspecified*))))) + (ctor (extract-field table spec) ...))))) (define-syntax-rule (define-json-writer record->json spec ...) "Define RECORD->JSON as a procedure that converts a RECORD into its JSON representation following SPEC, a series of field specifications." (define (record->json record) (let-syntax ((extract-field (syntax-rules () - ((_ (field getter key json->value value->scm)) + ((_ (field getter key scm->value value->scm)) (cons key (value->scm (getter record)))) - ((_ (field getter key json->value)) + ((_ (field getter key scm->value)) (cons key (getter record))) ((_ (field getter key)) (cons key (getter record))) @@ -78,24 +81,24 @@ created by CTOR and following SPEC, a series of field specifications." (define (scm->record table) (let-syntax ((extract-field (syntax-rules () - ((_ table (field key json->value value->scm)) - (json->value (assoc-ref table key))) - ((_ table (field key json->value)) - (json->value (assoc-ref table key))) + ((_ table (field key scm->value value->scm)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) + ((_ table (field key scm->value)) + (scm->value (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*))) ((_ table (field key)) - (assoc-ref table key)) + (if (pair? (assoc key table)) (cdr (assoc key table)) *unspecified*)) ((_ table (field)) - (assoc-ref table (symbol->string 'field)))))) - (ctor (or (extract-field table spec) *unspecified*) ...)))) + (if (pair? (assoc (symbol->string 'field) table)) (cdr (assoc (symbol->string 'field) table)) *unspecified*))))) + (ctor (extract-field table spec) ...)))) (define-syntax-rule (define-native-writer record->scm spec ...) "Define RECORD->SCM as a procedure that converts a RECORD into it an alist representation following SPEC, a series of field specifications." (define (record->scm record) (let-syntax ((extract-field (syntax-rules () - ((_ (field getter key json->value value->scm)) + ((_ (field getter key scm->value value->scm)) (cons key (value->scm (getter record)))) - ((_ (field getter key json->value)) + ((_ (field getter key scm->value)) (cons key (getter record))) ((_ (field getter key)) (cons key (getter record))) @@ -107,9 +110,12 @@ (define-syntax define-json-mapping (syntax-rules (<=>) "Define RTD as a record type with the given FIELDs and GETTERs, ?? la SRFI-9, -and define JSON->RECORD as a conversion from JSON to a record of this -type. Optionall, define RECORD->JSON as a conversion from a record of this -type to JSON." +and define JSON->RECORD as a conversion from JSON (from a port, string or alist) +to a record of this type. Optionally, define RECORD->JSON as a conversion from a +record of this type to a JSON string. Additionaly, define SCM->RECORD as a +conversion from an alist to a record of this type (equivalent to JSON->RECORD +when passing an alist) and RECORD->SCM as a conversion from a record of this +type to an alist." ((_ rtd ctor pred json->record (field getter spec ...) ...) (begin (define-record-type rtd @@ -150,4 +156,68 @@ (define-native-writer record->scm (field getter spec ...) ...))))) +(define-syntax define-json-type + (lambda (x) + "Define RTD as a record type with the given FIELDs. This will automatically +define a record and its constructor, predicate and fields with their getters as +they would be defined by define-json-mapping." + (define (gen-id template-id . args) + (datum->syntax + template-id + (string->symbol + (apply string-append + (map (lambda (x) + (if (string? x) x (symbol->string (syntax->datum x)))) + args))))) + (define (cleanup-single-rtd template-id) + (datum->syntax + template-id + (string->symbol + (string-delete + (lambda (c) (or (eq? c #\<) (eq? c #\>))) + (symbol->string (syntax->datum template-id)))))) + (define (cleanup-vector-rtd template-id) + (cleanup-single-rtd (datum->syntax template-id (vector-ref (syntax->datum template-id) 0)))) + + (define (cleanup-rtd template-id) + (if (vector? (syntax->datum template-id)) + (cleanup-vector-rtd template-id) + (cleanup-single-rtd template-id))) + (syntax-case x (<=>) + ((_ rtd field ...) + (with-syntax ((mapping-rtd #'rtd) + (constructor (gen-id #'rtd "make-" (cleanup-rtd #'rtd))) + (predicate (gen-id #'rtd (cleanup-rtd #'rtd) "?")) + (json->record (gen-id #'rtd "json->" (cleanup-rtd #'rtd))) + (record->json (gen-id #'rtd (cleanup-rtd #'rtd) "->json")) + (scm->record (gen-id #'rtd "scm->" (cleanup-rtd #'rtd))) + (record->scm (gen-id #'rtd (cleanup-rtd #'rtd) "->scm")) + ((fields ...) + (map + (lambda (f) + (syntax-case f () + ((name) + #`(name #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name))) + ((name key) + #`(name #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name) key)) + ((name key field-rtd) + #`(name + #,(gen-id #'rtd (cleanup-rtd #'rtd) "-" #'name) + key + #,(if (vector? (syntax->datum #'field-rtd)) + #`(lambda (v) (map #,(gen-id #'field-rtd "scm->" (cleanup-rtd #'field-rtd)) + (vector->list v))) + (gen-id #'field-rtd "scm->" (cleanup-rtd #'field-rtd))) + #,(if (vector? (syntax->datum #'field-rtd)) + #`(lambda (v) + (list->vector + (map #,(gen-id #'field-rtd (cleanup-rtd #'field-rtd) "->scm") v))) + (gen-id #'field-rtd (cleanup-rtd #'field-rtd) "->scm" )))))) + #'(field ...)))) + #'(define-json-mapping mapping-rtd + constructor + predicate + json->record <=> record->json <=> scm->record <=> record->scm + fields ...)))))) + ;;; (json record) ends here diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/pkg-list.scm new/guile-json-4.5.2/pkg-list.scm --- old/guile-json-4.4.0/pkg-list.scm 2020-10-22 22:33:09.000000000 +0200 +++ new/guile-json-4.5.2/pkg-list.scm 1970-01-01 01:00:00.000000000 +0100 @@ -1,29 +0,0 @@ -;; -;; Copyright (C) 2013-2018 Aleix Conchillo Flaque <aconchi...@gmail.com> -;; -;; This file is part of guile-json. -;; -;; guile-json is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3 of the License, or -;; (at your option) any later version. -;; -;; guile-json is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with guile-json. If not, see https://www.gnu.org/licenses/. -;; - -(package (json (4 4 0)) - (depends (srfi-1)) - (synopsis "JSON parser/writer for Guile") - (description - "guile-json supports the parsing and writing of JSON from Guile." - "It aims to be fully compliant with the json.org specification, and" - "is released under the GPLv3.") - (homepage "https://github.com/aconchillo/guile-json") - (libraries "json.scm" "json") - (documentation "README" "COPYING")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/tests/test-parser.scm new/guile-json-4.5.2/tests/test-parser.scm --- old/guile-json-4.4.0/tests/test-parser.scm 2020-07-23 21:09:24.000000000 +0200 +++ new/guile-json-4.5.2/tests/test-parser.scm 2020-11-29 06:37:22.000000000 +0100 @@ -81,6 +81,8 @@ (test-equal #(1 2 3 4) (json-string->scm " [ 1 , 2 , 3,4 ] ")) (test-equal #(1 2 #(3 4) #(5 6 #(7 8))) (json-string->scm "[1,2,[3,4],[5,6,[7,8]]]" )) (test-equal #(1 "two" 3 "four") (json-string->scm "[1,\"two\",3,\"four\"]")) +(test-error #t (json-string->scm "[,]")) +(test-error #t (json-string->scm "[,1]")) (test-error #t (json-string->scm "[1,2,,,5]")) (test-error #t (json-string->scm "[1,2")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/guile-json-4.4.0/tests/test-record.scm new/guile-json-4.5.2/tests/test-record.scm --- old/guile-json-4.4.0/tests/test-record.scm 2020-10-22 22:31:04.000000000 +0200 +++ new/guile-json-4.5.2/tests/test-record.scm 2021-01-11 18:30:37.000000000 +0100 @@ -1,6 +1,6 @@ ;;; (tests test-record) --- Guile JSON implementation. -;; Copyright (C) 2020 Aleix Conchillo Flaque <aconchi...@gmail.com> +;; Copyright (C) 2020-2021 Aleix Conchillo Flaque <aconchi...@gmail.com> ;; ;; This file is part of guile-json. ;; @@ -104,21 +104,24 @@ json->account <=> account->json (id account-id) (username account-username) - (omitted account-omitted)) + (omitted account-omitted) + (boolean account-boolean)) (define test-json-account - "{\"id\":\"11111\",\"username\":\"jane\"}") + "{\"id\":\"11111\",\"username\":\"jane\",\"boolean\":false}") (define test-account (json->account test-json-account)) (test-equal "11111" (account-id test-account)) (test-equal "jane" (account-username test-account)) (test-equal *unspecified* (account-omitted test-account)) +(test-equal #f (account-boolean test-account)) ;; Check idempotence (define test-account-idem (json->account (account->json test-account))) (test-equal "11111" (account-id test-account-idem)) (test-equal "jane" (account-username test-account-idem)) (test-equal *unspecified* (account-omitted test-account-idem)) +(test-equal #f (account-boolean test-account-idem)) ;; Nested records @@ -152,6 +155,57 @@ (test-equal (make-account "11111" "jane" (list (make-link "test" "http://guile.json"))) (json->account (account->json test-account))) +;; Check JSON types + +(define-json-type <account-type> + (id "id") + (username)) + +(define test-json-account-type + "{\"id\":\"11111\",\"username\":\"jane\"}") + +(define test-account-type (json->account-type test-json-account-type)) +(test-equal "11111" (account-type-id test-account-type)) +(test-equal "jane" (account-type-username test-account-type)) + +;; Check JSON types with nested objects. + +(define-json-type <link-type> + (type) + (url)) + +(define-json-type <account-type> + (id) + (username) + (link "link" <link-type>)) + +(define test-account-type + (make-account-type "11111" "jane" (make-link-type "test" "http://guile.json"))) +(test-equal "11111" (account-type-id test-account-type)) +(test-equal "jane" (account-type-username test-account-type)) +(test-equal (make-link-type "test" "http://guile.json") + (account-type-link test-account-type)) + +(test-equal "{\"id\":\"11111\",\"username\":\"jane\",\"link\":{\"type\":\"test\",\"url\":\"http://guile.json\"}}" + (account-type->json test-account-type)) + +;; Check JSON types with vectors. + +(define-json-type <account-type> + (id) + (username) + (links "links" #(<link-type>))) + +(define test-account-type + (make-account-type "11111" "jane" (list (make-link-type "test" "http://guile.json")))) +(test-equal "11111" (account-type-id test-account-type)) +(test-equal "jane" (account-type-username test-account-type)) +(test-equal (make-link-type "test" "http://guile.json") + (car (account-type-links test-account-type))) + +(test-equal "{\"id\":\"11111\",\"username\":\"jane\",\"links\":[{\"type\":\"test\",\"url\":\"http://guile.json\"}]}" + (account-type->json test-account-type)) + (exit (if (test-end "test-record") 0 1)) ;;; (tests test-record) ends here