@@ -73,7 +73,7 @@ typedef enum /* required operations on state stack */
73
73
static void json_validate_cstring (char * input );
74
74
static void json_lex (JsonLexContext * lex );
75
75
static 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 );
77
77
static void report_parse_error (JsonParseStack * stack , JsonLexContext * lex );
78
78
static void report_invalid_token (JsonLexContext * lex );
79
79
static int report_json_context (JsonLexContext * lex );
@@ -89,8 +89,6 @@ static void array_to_json_internal(Datum array, StringInfo result,
89
89
90
90
/* fake type category for JSON so we can distinguish it in datum_to_json */
91
91
#define TYPCATEGORY_JSON 'j'
92
- /* letters appearing in numeric output that aren't valid in a JSON number */
93
- #define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
94
92
/* chars to consider as part of an alphanumeric token */
95
93
#define JSON_ALPHANUMERIC_CHAR (c ) \
96
94
(((c) >= 'a' && (c) <= 'z') || \
@@ -361,13 +359,13 @@ json_lex(JsonLexContext *lex)
361
359
else if (* s == '-' )
362
360
{
363
361
/* Negative number. */
364
- json_lex_number (lex , s + 1 );
362
+ json_lex_number (lex , s + 1 , NULL );
365
363
lex -> token_type = JSON_VALUE_NUMBER ;
366
364
}
367
365
else if (* s >= '0' && * s <= '9' )
368
366
{
369
367
/* Positive number. */
370
- json_lex_number (lex , s );
368
+ json_lex_number (lex , s , NULL );
371
369
lex -> token_type = JSON_VALUE_NUMBER ;
372
370
}
373
371
else
@@ -530,7 +528,7 @@ json_lex_string(JsonLexContext *lex)
530
528
*-------------------------------------------------------------------------
531
529
*/
532
530
static void
533
- json_lex_number (JsonLexContext * lex , char * s )
531
+ json_lex_number (JsonLexContext * lex , char * s , bool * num_err )
534
532
{
535
533
bool error = false;
536
534
char * p ;
@@ -584,15 +582,24 @@ json_lex_number(JsonLexContext *lex, char *s)
584
582
}
585
583
586
584
/*
587
- * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
585
+ * Check for trailing garbage. As in json_lex(), any alphanumeric stuff
588
586
* here should be considered part of the token for error-reporting
589
587
* purposes.
590
588
*/
591
589
for (p = s ; JSON_ALPHANUMERIC_CHAR (* p ); p ++ )
592
590
error = 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
+ }
596
603
}
597
604
598
605
/*
@@ -819,6 +826,8 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
819
826
TYPCATEGORY tcategory , Oid typoutputfunc )
820
827
{
821
828
char * outputstr ;
829
+ bool numeric_error ;
830
+ JsonLexContext dummy_lex ;
822
831
823
832
if (is_null )
824
833
{
@@ -845,11 +854,10 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
845
854
846
855
/*
847
856
* 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.
851
857
*/
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 )
853
861
appendStringInfoString (result , outputstr );
854
862
else
855
863
escape_json (result , outputstr );
0 commit comments