diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 1486eda..af8ddc6 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -50,7 +50,7 @@ typedef enum					/* contexts of JSON parser */
 
 static inline void json_lex(JsonLexContext *lex);
 static inline void json_lex_string(JsonLexContext *lex);
-static inline void json_lex_number(JsonLexContext *lex, char *s);
+static inline void json_lex_number(JsonLexContext *lex, char *s, bool *num_err);
 static inline void parse_scalar(JsonLexContext *lex, JsonSemAction *sem);
 static void parse_object_field(JsonLexContext *lex, JsonSemAction *sem);
 static void parse_object(JsonLexContext *lex, JsonSemAction *sem);
@@ -147,8 +147,6 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
 #define TYPCATEGORY_JSON 'j'
 /* fake category for types that have a cast to json */
 #define TYPCATEGORY_JSON_CAST 'c'
-/* letters appearing in numeric output that aren't valid in a JSON number */
-#define NON_NUMERIC_LETTER "NnAaIiFfTtYy"
 /* chars to consider as part of an alphanumeric token */
 #define JSON_ALPHANUMERIC_CHAR(c)  \
 	(((c) >= 'a' && (c) <= 'z') || \
@@ -567,7 +565,7 @@ json_lex(JsonLexContext *lex)
 				break;
 			case '-':
 				/* Negative number. */
-				json_lex_number(lex, s + 1);
+				json_lex_number(lex, s + 1, NULL);
 				lex->token_type = JSON_TOKEN_NUMBER;
 				break;
 			case '0':
@@ -581,7 +579,7 @@ json_lex(JsonLexContext *lex)
 			case '8':
 			case '9':
 				/* Positive number. */
-				json_lex_number(lex, s);
+				json_lex_number(lex, s, NULL);
 				lex->token_type = JSON_TOKEN_NUMBER;
 				break;
 			default:
@@ -903,7 +901,7 @@ json_lex_string(JsonLexContext *lex)
  *-------------------------------------------------------------------------
  */
 static inline void
-json_lex_number(JsonLexContext *lex, char *s)
+json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
 {
 	bool		error = false;
 	char	   *p;
@@ -976,10 +974,19 @@ json_lex_number(JsonLexContext *lex, char *s)
 	 */
 	for (p = s; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*p); p++, len++)
 		error = true;
-	lex->prev_token_terminator = lex->token_terminator;
-	lex->token_terminator = p;
-	if (error)
-		report_invalid_token(lex);
+
+	if (num_err != NULL)
+	{
+		/* let the caller handle the error */
+		*num_err = error;
+	}
+	else
+	{
+		lex->prev_token_terminator = lex->token_terminator;
+		lex->token_terminator = p;
+		if (error)
+			report_invalid_token(lex);
+	}
 }
 
 /*
@@ -1214,6 +1221,8 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
 {
 	char	   *outputstr;
 	text	   *jsontext;
+	bool       numeric_error;
+	JsonLexContext dummy_lex;
 
 	if (is_null)
 	{
@@ -1237,14 +1246,13 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
 			break;
 		case TYPCATEGORY_NUMERIC:
 			outputstr = OidOutputFunctionCall(typoutputfunc, val);
-
 			/*
 			 * 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)
+			dummy_lex.input = *outputstr == '-' ? outputstr + 1 : outputstr;
+			dummy_lex.input_length = strlen(dummy_lex.input);
+			json_lex_number(&dummy_lex, dummy_lex.input, &numeric_error);
+			if (! numeric_error)
 				appendStringInfoString(result, outputstr);
 			else
 				escape_json(result, outputstr);
