@@ -73,7 +73,7 @@ typedef enum/* required operations on state stack */
7373static void json_validate_cstring (char * input );
7474static void json_lex (JsonLexContext * lex );
7575static void json_lex_string (JsonLexContext * lex );
76- static void json_lex_number (JsonLexContext * lex ,char * s );
76+ static void json_lex_number (JsonLexContext * lex ,char * s , bool * num_err );
7777static void report_parse_error (JsonParseStack * stack ,JsonLexContext * lex );
7878static void report_invalid_token (JsonLexContext * lex );
7979static int report_json_context (JsonLexContext * lex );
@@ -89,8 +89,6 @@ static void array_to_json_internal(Datum array, StringInfo result,
8989
9090/* fake type category for JSON so we can distinguish it in datum_to_json */
9191#define TYPCATEGORY_JSON 'j'
92- /* letters appearing in numeric output that aren't valid in a JSON number */
93- #define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
9492/* chars to consider as part of an alphanumeric token */
9593#define JSON_ALPHANUMERIC_CHAR (c ) \
9694(((c) >= 'a' && (c) <= 'z') || \
@@ -361,13 +359,13 @@ json_lex(JsonLexContext *lex)
361359else if (* s == '-' )
362360{
363361/* Negative number. */
364- json_lex_number (lex ,s + 1 );
362+ json_lex_number (lex ,s + 1 , NULL );
365363lex -> token_type = JSON_VALUE_NUMBER ;
366364}
367365else if (* s >='0' && * s <='9' )
368366{
369367/* Positive number. */
370- json_lex_number (lex ,s );
368+ json_lex_number (lex ,s , NULL );
371369lex -> token_type = JSON_VALUE_NUMBER ;
372370}
373371else
@@ -530,7 +528,7 @@ json_lex_string(JsonLexContext *lex)
530528 *-------------------------------------------------------------------------
531529 */
532530static void
533- json_lex_number (JsonLexContext * lex ,char * s )
531+ json_lex_number (JsonLexContext * lex ,char * s , bool * num_err )
534532{
535533bool error = false;
536534char * p ;
@@ -584,15 +582,24 @@ json_lex_number(JsonLexContext *lex, char *s)
584582}
585583
586584/*
587- * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
585+ * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
588586 * here should be considered part of the token for error-reporting
589587 * purposes.
590588 */
591589for (p = s ;JSON_ALPHANUMERIC_CHAR (* p );p ++ )
592590error = true;
593- lex -> token_terminator = p ;
594- if (error )
595- report_invalid_token (lex );
591+
592+ if (num_err != NULL )
593+ {
594+ /* let the caller handle the error */
595+ * num_err = error ;
596+ }
597+ else
598+ {
599+ lex -> token_terminator = p ;
600+ if (error )
601+ report_invalid_token (lex );
602+ }
596603}
597604
598605/*
@@ -819,6 +826,8 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
819826TYPCATEGORY tcategory ,Oid typoutputfunc )
820827{
821828char * outputstr ;
829+ bool numeric_error ;
830+ JsonLexContext dummy_lex ;
822831
823832if (is_null )
824833{
@@ -845,11 +854,10 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
845854
846855/*
847856 * Don't call escape_json here if it's a valid JSON number.
848- * Numeric output should usually be a valid JSON number and JSON
849- * numbers shouldn't be quoted. Quote cases like "Nan" and
850- * "Infinity", however.
851857 */
852- if (strpbrk (outputstr ,NON_NUMERIC_LETTER )== NULL )
858+ dummy_lex .input = * outputstr == '-' ?outputstr + 1 :outputstr ;
859+ json_lex_number (& dummy_lex ,dummy_lex .input ,& numeric_error );
860+ if (!numeric_error )
853861appendStringInfoString (result ,outputstr );
854862else
855863escape_json (result ,outputstr );