diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-07-06 16:40:27 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-07-06 16:40:27 -0700 |
commit | e12b6c208c0e591bc0feea52bf50fcad4e8e8b69 (patch) | |
tree | 6528a01b1be5e9781d730f7a17143994bba1ba26 | |
parent | 2414f36adfae87c548d8b05e474c5ccda6df5fd6 (diff) | |
download | txr-e12b6c208c0e591bc0feea52bf50fcad4e8e8b69.tar.gz txr-e12b6c208c0e591bc0feea52bf50fcad4e8e8b69.tar.bz2 txr-e12b6c208c0e591bc0feea52bf50fcad4e8e8b69.zip |
json: support printing structs in JSON format.
* lib.c (out_json_sym): New static function.
(out_json_rec): Handle structp.
* txr.1: Documented.
-rw-r--r-- | lib.c | 62 | ||||
-rw-r--r-- | txr.1 | 16 |
2 files changed, 78 insertions, 0 deletions
@@ -14820,6 +14820,16 @@ static int check_emit_circle(val obj, val out, struct strm_ctx *ctx, val self) return 0; } +static void out_json_sym(val sym, val out, struct strm_ctx *ctx) +{ + put_char(chr('"'), out); + if (ctx) + obj_print_impl(sym, out, nil, ctx); + else + obj_print(sym, out, nil); + put_char(chr('"'), out); +} + static void out_json_rec(val obj, val out, enum json_fmt jf, struct strm_ctx *ctx) { @@ -15026,6 +15036,58 @@ static void out_json_rec(val obj, val out, enum json_fmt jf, force_break(out); return; } + if (structp(obj)) { + val ty = typeof(obj); + val sl = slots(ty); + val iter; + val save_indent; + int force_br = 0; + + if (jf == json_fmt_standard) { + put_string(lit("{\n"), out); + save_indent = inc_indent_abs(out, two); + put_string(lit("\"__type\" : "), out); + out_json_sym(ty, out, ctx); + + for (iter = sl; iter; iter = cdr(iter)) { + val slsym = car(iter); + + if (static_slot_p(ty, slsym)) + continue; + + put_string(lit(",\n"), out); + out_json_sym(slsym, out, ctx); + put_string(lit(" : "), out); + out_json_rec(slot(obj, slsym), out, jf, ctx); + } + put_string(lit("\n"), out); + } else { + put_char(chr('{'), out); + save_indent = inc_indent(out, zero); + put_string(lit("\"__type\":"), out); + out_json_sym(ty, out, ctx); + + for (iter = sl; iter; iter = cdr(iter)) { + val slsym = car(iter); + + if (static_slot_p(ty, slsym)) + continue; + + put_string(lit(","), out); + if (width_check(out, nil)) + force_br = 1; + out_json_sym(slsym, out, ctx); + put_string(lit(":"), out); + out_json_rec(slot(obj, slsym), out, jf, ctx); + } + } + + set_indent(out, save_indent); + put_char(chr('}'), out); + if (force_br) + force_break(out); + return; + } break; case FLNUM: case NUM: @@ -84092,6 +84092,22 @@ 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. +A structure object is rendered into JSON using the +.code {} +object notation. The keys of the objects are the names of the +symbols of the object type's non-static slots, appearing as a +string. The values are the values of the slots. They must be JSON-conforming +objects. +The first entry of the object is a key named +.str __type +whose value is the structure type symbol, appearing as a string. +Both the slot symbols and the type symbol may appear with a package +qualifier, depending on the relationship of the symbols to the current +package, according to similar rules as if the symbol were printed +by the +.code print +function. + 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. |