mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +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);
|
Oid typoutputfunc, bool use_line_feeds);
|
||||||
static void array_to_json_internal(Datum array, StringInfo result, 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.
|
* Input.
|
||||||
*/
|
*/
|
||||||
@ -707,10 +711,20 @@ datum_to_json(Datum val, StringInfo result, TYPCATEGORY tcategory,
|
|||||||
case TYPCATEGORY_NUMERIC:
|
case TYPCATEGORY_NUMERIC:
|
||||||
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
outputstr = OidOutputFunctionCall(typoutputfunc, val);
|
||||||
/*
|
/*
|
||||||
* Don't call escape_json here. Numeric output should
|
* Don't call escape_json here if it's a valid JSON
|
||||||
* be a valid JSON number and JSON numbers shouldn't
|
* number. Numeric output should usually be a valid
|
||||||
* be quoted.
|
* 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);
|
appendStringInfoString(result, outputstr);
|
||||||
pfree(outputstr);
|
pfree(outputstr);
|
||||||
break;
|
break;
|
||||||
@ -806,9 +820,10 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
|
|||||||
typalign, &elements, &nulls,
|
typalign, &elements, &nulls,
|
||||||
&nitems);
|
&nitems);
|
||||||
|
|
||||||
/* can't have an array of arrays, so this is the only special case here */
|
|
||||||
if (element_type == RECORDOID)
|
if (element_type == RECORDOID)
|
||||||
tcategory = TYPCATEGORY_COMPOSITE;
|
tcategory = TYPCATEGORY_COMPOSITE;
|
||||||
|
else if (element_type == JSONOID)
|
||||||
|
tcategory = TYPCATEGORY_JSON;
|
||||||
else
|
else
|
||||||
tcategory = TypeCategory(element_type);
|
tcategory = TypeCategory(element_type);
|
||||||
|
|
||||||
@ -876,6 +891,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
|
|||||||
tcategory = TYPCATEGORY_ARRAY;
|
tcategory = TYPCATEGORY_ARRAY;
|
||||||
else if (tupdesc->attrs[i]->atttypid == RECORDOID)
|
else if (tupdesc->attrs[i]->atttypid == RECORDOID)
|
||||||
tcategory = TYPCATEGORY_COMPOSITE;
|
tcategory = TYPCATEGORY_COMPOSITE;
|
||||||
|
else if (tupdesc->attrs[i]->atttypid == JSONOID)
|
||||||
|
tcategory = TYPCATEGORY_JSON;
|
||||||
else
|
else
|
||||||
tcategory = TypeCategory(tupdesc->attrs[i]->atttypid);
|
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]}
|
{"f1":[5,6,7,8,9,10]}
|
||||||
(1 row)
|
(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;
|
FROM rows q;
|
||||||
|
|
||||||
SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),false);
|
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