From 83fcaffea2b55152e45fdcaf3fdaf4c0c89f65ce Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Mon, 20 Feb 2012 15:01:03 -0500 Subject: 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. --- src/backend/utils/adt/json.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/backend/utils/adt/json.c') diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index 60addf2871f..feda0e00357 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -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); -- cgit v1.2.3