@@ -50,7 +50,7 @@ typedef enum /* contexts of JSON parser */
5050
5151static inline void json_lex (JsonLexContext * lex );
5252static inline void json_lex_string (JsonLexContext * lex );
53- static inline void json_lex_number (JsonLexContext * lex , char * s );
53+ static inline void json_lex_number (JsonLexContext * lex , char * s , bool * num_err );
5454static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
5555static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
5656static void parse_object (JsonLexContext * lex , JsonSemAction * sem );
@@ -147,8 +147,6 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
147147#define TYPCATEGORY_JSON 'j'
148148/* fake category for types that have a cast to json */
149149#define TYPCATEGORY_JSON_CAST 'c'
150- /* letters appearing in numeric output that aren't valid in a JSON number */
151- #define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
152150/* chars to consider as part of an alphanumeric token */
153151#define JSON_ALPHANUMERIC_CHAR (c ) \
154152 (((c) >= 'a' && (c) <= 'z') || \
@@ -567,7 +565,7 @@ json_lex(JsonLexContext *lex)
567565 break ;
568566 case '-' :
569567 /* Negative number. */
570- json_lex_number (lex , s + 1 );
568+ json_lex_number (lex , s + 1 , NULL );
571569 lex -> token_type = JSON_TOKEN_NUMBER ;
572570 break ;
573571 case '0' :
@@ -581,7 +579,7 @@ json_lex(JsonLexContext *lex)
581579 case '8' :
582580 case '9' :
583581 /* Positive number. */
584- json_lex_number (lex , s );
582+ json_lex_number (lex , s , NULL );
585583 lex -> token_type = JSON_TOKEN_NUMBER ;
586584 break ;
587585 default :
@@ -903,7 +901,7 @@ json_lex_string(JsonLexContext *lex)
903901 *-------------------------------------------------------------------------
904902 */
905903static inline void
906- json_lex_number (JsonLexContext * lex , char * s )
904+ json_lex_number (JsonLexContext * lex , char * s , bool * num_err )
907905{
908906 bool error = false;
909907 char * p ;
@@ -976,10 +974,19 @@ json_lex_number(JsonLexContext *lex, char *s)
976974 */
977975 for (p = s ; len < lex -> input_length && JSON_ALPHANUMERIC_CHAR (* p ); p ++ , len ++ )
978976 error = true;
979- lex -> prev_token_terminator = lex -> token_terminator ;
980- lex -> token_terminator = p ;
981- if (error )
982- report_invalid_token (lex );
977+
978+ if (num_err != NULL )
979+ {
980+ /* let the caller handle the error */
981+ * num_err = error ;
982+ }
983+ else
984+ {
985+ lex -> prev_token_terminator = lex -> token_terminator ;
986+ lex -> token_terminator = p ;
987+ if (error )
988+ report_invalid_token (lex );
989+ }
983990}
984991
985992/*
@@ -1214,6 +1221,8 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
12141221{
12151222 char * outputstr ;
12161223 text * jsontext ;
1224+ bool numeric_error ;
1225+ JsonLexContext dummy_lex ;
12171226
12181227 if (is_null )
12191228 {
@@ -1237,14 +1246,13 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
12371246 break ;
12381247 case TYPCATEGORY_NUMERIC :
12391248 outputstr = OidOutputFunctionCall (typoutputfunc , val );
1240-
12411249 /*
12421250 * Don't call escape_json here if it's a valid JSON number.
1243- * Numeric output should usually be a valid JSON number and JSON
1244- * numbers shouldn't be quoted. Quote cases like "Nan" and
1245- * "Infinity", however.
12461251 */
1247- if (strpbrk (outputstr , NON_NUMERIC_LETTER ) == NULL )
1252+ dummy_lex .input = * outputstr == '-' ? outputstr + 1 : outputstr ;
1253+ dummy_lex .input_length = strlen (dummy_lex .input );
1254+ json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error );
1255+ if (! numeric_error )
12481256 appendStringInfoString (result , outputstr );
12491257 else
12501258 escape_json (result , outputstr );
0 commit comments