summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-09-03 20:34:22 -0700
committerKaz Kylheku <kaz@kylheku.com>2023-09-03 20:34:22 -0700
commitf9c7296269adc16675c96535a9bde8b7686866c0 (patch)
treef15011d4f35818c29143b010f46bf3c9d7ba52a4
parent004dcc459539ce03587cfe3bdef0fd3c4ec68809 (diff)
downloadtxr-f9c7296269adc16675c96535a9bde8b7686866c0.tar.gz
txr-f9c7296269adc16675c96535a9bde8b7686866c0.tar.bz2
txr-f9c7296269adc16675c96535a9bde8b7686866c0.zip
json: allow integers and lists.
* lib.c (out_json_rec): Handle NUM and BGNUM cases same as FLNUM so integers get printed. The restriction against integers has been largely unhelpful and bothersome. Handle LCONS together with CONS. Lists that are not special notation fall through to the VEC case, which now uses seq_iter_t iteration to handle vectors and lists. * tests/010/json.tl: New tests. * txr.1: Documented support for printing integers and lists.
-rw-r--r--lib.c22
-rw-r--r--tests/010/json.tl5
-rw-r--r--txr.112
3 files changed, 30 insertions, 9 deletions
diff --git a/lib.c b/lib.c
index 422dbe57..3259ab1b 100644
--- a/lib.c
+++ b/lib.c
@@ -14412,6 +14412,7 @@ static void out_json_rec(val obj, val out, enum json_fmt jf,
return;
}
break;
+ case LCONS:
case CONS:
if (ctx != 0) {
val sym = car(obj);
@@ -14504,13 +14505,14 @@ static void out_json_rec(val obj, val out, enum json_fmt jf,
return;
}
}
- break;
+ /* fallthrough */
case VEC:
{
val save_indent;
int force_br = 0;
- cnum len = c_num(length(obj), self);
- cnum i;
+ seq_iter_t si;
+ val elem;
+ seq_iter_init(self, &si, obj);
if (jf == json_fmt_standard) {
put_string(lit("[\n"), out);
@@ -14520,19 +14522,23 @@ static void out_json_rec(val obj, val out, enum json_fmt jf,
save_indent = inc_indent(out, zero);
}
- for (i = 0; i < len; i++) {
- val elem = obj->v.vec[i];
+ if (seq_get(&si, &elem)) for (;;) {
+ val nxelem;
+ int more = seq_get(&si, &nxelem);
out_json_rec(elem, out, jf, ctx);
if (jf == json_fmt_standard) {
- if (i < len - 1)
+ if (more)
put_string(lit(",\n"), out);
else
put_char(chr('\n'), out);
- } else if (i < len - 1) {
+ } else if (more) {
put_char(chr(','), out);
if (width_check(out, nil))
force_br = 1;
}
+ if (!more)
+ break;
+ elem = nxelem;
}
set_indent(out, save_indent);
put_char(chr(']'), out);
@@ -14592,6 +14598,8 @@ static void out_json_rec(val obj, val out, enum json_fmt jf,
}
break;
case FLNUM:
+ case NUM:
+ case BGNUM:
format(out, lit("~a"), obj, nao);
return;
case LIT:
diff --git a/tests/010/json.tl b/tests/010/json.tl
index dfd45173..f613c93a 100644
--- a/tests/010/json.tl
+++ b/tests/010/json.tl
@@ -184,3 +184,8 @@
(command-put-jsons `cat > @name` '(#() 1.0 nil)) t
(file-get-string name) "[]\n1\nfalse\n"
(command-get-jsons `cat @name`) (#() 1.0 nil))))
+
+(mtest
+ (tojson 1) "1"
+ (tojson 123123123123123123123123123123) "123123123123123123123123123123"
+ (tojson '(1 2 3 4 5)) "[1,2,3,4,5]")
diff --git a/txr.1 b/txr.1
index eb20732e..555bbed1 100644
--- a/txr.1
+++ b/txr.1
@@ -82127,11 +82127,11 @@ and
.codn null ,
respectively.
.IP 2.
-a floating-point number.
+a floating-point number or integer.
.IP 3.
a character string.
.IP 4.
-a vector of JSON-conforming objects.
+a vector or list of JSON-conforming objects.
.IP 5.
a hash table whose keys and values are JSON-conforming objects.
.RE
@@ -82139,6 +82139,14 @@ a hash table whose keys and values are JSON-conforming objects.
Note that unless the keys in a hash table are all strings, nonstandard JSON
is produced, since RFC 8259 requires JSON object keys to be strings.
+A list of object is rendered in the same way as vector, in the JSON
+.code []
+notation. When such JSON notation is parsed, a vector is produced.
+
+When integer objects are output, they may not constitute valid JSON, since the
+JSON specification supports only IEEE 64 bit floating-point numbers. JSON
+numbers are read as floating-point.
+
If the
.code flat-p
argument is present and has a true value, then the JSON is generated