mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Fix a couple of cases of JSON output.
First, as noted by Itagaki Takahiro, a datum of type JSON doesn't need to be escaped. Second, ensure that numeric output not in the form of a legal JSON number is quoted and escaped.
This commit is contained in:
parent
5223f96d92
commit
83fcaffea2
@ -84,6 +84,10 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims,int * dims,
|
||||
Oid typoutputfunc, bool use_line_feeds);
|
||||
static void array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds);
|
||||
|
||||
/* fake type category for JSON so we can distinguish it in datum_to_json */
|
||||
#define TYPCATEGORY_JSON 'j'
|
||||
/* letters appearing in numeric output that aren't valid in a JSON number */
|
||||
#define NON_NUMERIC_LETTER "NnAnIiFfTtYy"
|
||||
/*
|
||||
* Input.
|
||||
*/
|
||||
@ -707,10 +711,20 @@ datum_to_json(Datum val, StringInfo result, TYPCATEGORY tcategory,
|
||||
case TYPCATEGORY_NUMERIC:
|
||||
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
||||
/*
|
||||
* Don't call escape_json here. Numeric output should
|
||||
* be a valid JSON number and JSON numbers shouldn't
|
||||
* be quoted.
|
||||
* Don't call escape_json here if it's a valid JSON
|
||||
* number. Numeric output should usually be a valid
|
||||
* JSON number and JSON numbers shouldn't be quoted.
|
||||
* Quote cases like "Nan" and "Infinity", however.
|
||||
*/
|
||||
if (strpbrk(outputstr,NON_NUMERIC_LETTER) == NULL)
|
||||
appendStringInfoString(result, outputstr);
|
||||
else
|
||||
escape_json(result, outputstr);
|
||||
pfree(outputstr);
|
||||
break;
|
||||
case TYPCATEGORY_JSON:
|
||||
/* JSON will already be escaped */
|
||||
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
||||
appendStringInfoString(result, outputstr);
|
||||
pfree(outputstr);
|
||||
break;
|
||||
@ -806,9 +820,10 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
|
||||
typalign, &elements, &nulls,
|
||||
&nitems);
|
||||
|
||||
/* can't have an array of arrays, so this is the only special case here */
|
||||
if (element_type == RECORDOID)
|
||||
tcategory = TYPCATEGORY_COMPOSITE;
|
||||
else if (element_type == JSONOID)
|
||||
tcategory = TYPCATEGORY_JSON;
|
||||
else
|
||||
tcategory = TypeCategory(element_type);
|
||||
|
||||
@ -876,6 +891,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
||||
tcategory = TYPCATEGORY_ARRAY;
|
||||
else if (tupdesc->attrs[i]->atttypid == RECORDOID)
|
||||
tcategory = TYPCATEGORY_COMPOSITE;
|
||||
else if (tupdesc->attrs[i]->atttypid == JSONOID)
|
||||
tcategory = TYPCATEGORY_JSON;
|
||||
else
|
||||
tcategory = TypeCategory(tupdesc->attrs[i]->atttypid);
|
||||
|
||||
|
@ -367,3 +367,33 @@ SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),
|
||||
{"f1":[5,6,7,8,9,10]}
|
||||
(1 row)
|
||||
|
||||
-- non-numeric output
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT 'NaN'::float8 AS "float8field") q;
|
||||
row_to_json
|
||||
-----------------------
|
||||
{"float8field":"NaN"}
|
||||
(1 row)
|
||||
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT 'Infinity'::float8 AS "float8field") q;
|
||||
row_to_json
|
||||
----------------------------
|
||||
{"float8field":"Infinity"}
|
||||
(1 row)
|
||||
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT '-Infinity'::float8 AS "float8field") q;
|
||||
row_to_json
|
||||
-----------------------------
|
||||
{"float8field":"-Infinity"}
|
||||
(1 row)
|
||||
|
||||
-- json input
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT '{"a":1,"b": [2,3,4,"d","e","f"],"c":{"p":1,"q":2}}'::json AS "jsonfield") q;
|
||||
row_to_json
|
||||
------------------------------------------------------------------
|
||||
{"jsonfield":{"a":1,"b": [2,3,4,"d","e","f"],"c":{"p":1,"q":2}}}
|
||||
(1 row)
|
||||
|
||||
|
@ -97,3 +97,18 @@ SELECT row_to_json(q,true)
|
||||
FROM rows q;
|
||||
|
||||
SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),false);
|
||||
|
||||
-- non-numeric output
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT 'NaN'::float8 AS "float8field") q;
|
||||
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT 'Infinity'::float8 AS "float8field") q;
|
||||
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT '-Infinity'::float8 AS "float8field") q;
|
||||
|
||||
-- json input
|
||||
SELECT row_to_json(q)
|
||||
FROM (SELECT '{"a":1,"b": [2,3,4,"d","e","f"],"c":{"p":1,"q":2}}'::json AS "jsonfield") q;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user