diff options
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | lib.c | 21 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | share/txr/stdlib/doc-syms.tl | 1 | ||||
-rw-r--r-- | txr.1 | 66 |
5 files changed, 90 insertions, 0 deletions
@@ -6873,6 +6873,7 @@ void eval_init(void) reg_fun(intern(lit("prinl"), user_package), func_n2o(prinl, 1)); reg_fun(intern(lit("pprinl"), user_package), func_n2o(pprinl, 1)); reg_fun(intern(lit("tprint"), user_package), func_n2o(tprint, 1)); + reg_fun(intern(lit("tojson"), user_package), func_n2o(tojson, 1)); reg_fun(intern(lit("display-width"), user_package), func_n1(display_width)); reg_fun(intern(lit("fmt-simple"), system_package), func_n5o(fmt_simple, 1)); @@ -13454,6 +13454,27 @@ val tostringp(val obj) return get_string_from_stream(ss); } +val tojson(val obj, val flat) +{ + if (consp(obj) && eq(car(obj), json_s)) { + val ss = make_string_output_stream(); + if (default_null_arg(flat)) + set_indent_mode(ss, num_fast(indent_foff)); + obj_print(obj, ss, nil); + return get_string_from_stream(ss); + } else { + val json = cons(json_s, cons(quote_s, cons(obj, nil))); + val ss = make_string_output_stream(); + if (default_null_arg(flat)) + set_indent_mode(ss, num_fast(indent_foff)); + obj_print(json, ss, nil); + rcyc_pop(&json); + rcyc_pop(&json); + rcyc_pop(&json); + return get_string_from_stream(ss); + } +} + val display_width(val obj) { if (stringp(obj)) { @@ -1206,6 +1206,7 @@ val print(val obj, val stream, val pretty); val pprint(val obj, val stream); val tostring(val obj); val tostringp(val obj); +val tojson(val obj, val flat); val display_width(val obj); #if !HAVE_SETENV void setenv(const char *name, const char *value, int overwrite); diff --git a/share/txr/stdlib/doc-syms.tl b/share/txr/stdlib/doc-syms.tl index 1b9eb503..1e12d115 100644 --- a/share/txr/stdlib/doc-syms.tl +++ b/share/txr/stdlib/doc-syms.tl @@ -1854,6 +1854,7 @@ ("tofloatz" "N-03E2D4B8") ("toint" "N-01DBC9D7") ("tointz" "N-03E2D4B8") + ("tojson" "N-017848BD") ("tok" "N-0117F60C") ("tok-str" "N-0225F28F") ("tok-where" "N-0225F28F") @@ -71808,6 +71808,72 @@ etc. .SS* Data Interchange Support +.coNP Function @ tojson +.synb +.mets (tojson < obj <> [ flat-p ]) +.syne +.desc +The +.code tojson +function converts +.meta obj +into JSON notation, returned as a character string. + +If +.meta obj +is +.code json +macro syntax generated by the parser, or else generated programmatically in a compatible way, +then this is converted back into JSON syntax. + +Otherwise if +.meta obj +conforms to the conventions by which JSON objects are represented in Lisp, +it is converted to JSON syntax also. + +The behavior is unspecified if +.meta obj +or any component of +.meta obj +is an object incompatible with the JSON representation conventions. +An exception may be thrown. + +An object conforms to the JSON representation conventions if: +.RS +.IP 1. +It is one of the symbols +.codn nil , +.code t +or +.codn null , +which map to the JSON keywords +.codn false , +.code true +and +.codn null , +respectively. +.IP 2. +It is a floating-point number. +.IP 3. +It is a character string. +.IP 4. +It is a vector of JSON-conforming objects. +.IP 5. +It is a hash table whose keys and values are JSON-conforming objects. +.RE +.IP +Note that if unless the keys in a hash table are all strings, nonstandard JSON +is produced, since RFC 8259 requires JSON object keys to be strings. + +If the +.code flat-p +argument is present and has a true value, then the JSON is generated +without any line breaks or indentation. + +Otherwise, the JSON is potentially subject to such formatting. + +Even if the JSON data contains line breaks, it does not end in a line break. + .coNP Macro @ json .synb .mets (json [quote | sys:qquote] << object ) |