json_fixed_lexer-20100919.diff
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/adt/json.c | 72 | 19 |
| src/backend/utils/adt/json_scanner.l | 5 | 3 |
| src/backend/utils/adt/Makefile | 4 | 0 |
| src/include/catalog/pg_proc.h | 1 | 0 |
| src/test/regress/expected/json.out | 365 | 3 |
| src/test/regress/sql/json.sql | 29 | 0 |
| src/test/regress/sql/json_test_strings.sql | 264 | 0 |
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index 483abb6..2c035b1 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -50,6 +50,8 @@ else
@$(missing) bison $< $@
endif
+json_scanner.h: json_scanner.c ;
+
json_scanner.c: json_scanner.l
ifdef FLEX
$(FLEX) $(FLEXFLAGS) -o'$@' $<
@@ -59,4 +61,6 @@ endif
json_parser.o keywords.o parser.o: json_parser.h
+json.c: json_parser.h json_scanner.h
+
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 13e5391..9a3979e 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -20,7 +20,9 @@
#include "json_parser.h"
#include "json_scanner.h"
-static Json *json_parse(const char *str, int len, bool validateOnly);
+static Json *json_parse(const char *str, int len);
+static bool json_validate(const char *str, int len);
+static Json *json_parse_or_validate(const char *str, int len, bool *validate);
static void json_free(Json *node);
static void append_json(StringInfo buf, const Json *node, int indent);
static void append_indent(StringInfo buf, int indent);
@@ -43,11 +45,12 @@ json_in(PG_FUNCTION_ARGS)
json = (jsontype *) cstring_to_text(s);
- /*
- * Parse the data to check if it is a JSON data. Assume that
- * ERROR occurred if parsing failed.
- */
- json_parse(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json), true);
+ if (!json_validate(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json)))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for JSON")));
+ }
PG_RETURN_JSON_P(json);
}
@@ -68,7 +71,12 @@ json_recv(PG_FUNCTION_ARGS)
int nbytes;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
- json_parse(str, nbytes, true);
+ if (!json_validate(str, nbytes))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+ errmsg("invalid input syntax for JSON")));
+ }
result = (jsontype *) cstring_to_text_with_len(str, nbytes);
pfree(str);
@@ -82,12 +90,31 @@ json_send(PG_FUNCTION_ARGS)
return textsend(fcinfo);
}
+/* json_validate(text). Renamed to avoid clashing
+ * with the C function json_validate. */
+PG_FUNCTION_INFO_V1(json_validate_f);
+Datum json_validate_f(PG_FUNCTION_ARGS);
+Datum
+json_validate_f(PG_FUNCTION_ARGS)
+{
+ jsontype *t = PG_GETARG_JSON_P(0);
+ bool ret;
+
+ ret = json_validate(VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
+ PG_RETURN_BOOL(ret);
+}
+
Datum
text_to_json(PG_FUNCTION_ARGS)
{
text *t = PG_GETARG_TEXT_PP(0);
- json_parse(VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t), true);
+ if (!json_validate(VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t)))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for JSON")));
+ }
PG_RETURN_JSON_P((jsontype *) t);
}
@@ -106,7 +133,7 @@ json_pretty(PG_FUNCTION_ARGS)
Json *node;
StringInfoData buf;
- node = json_parse(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json), false);
+ node = json_parse(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json));
initStringInfo(&buf);
append_json(&buf, node, 0);
json_free(node);
@@ -115,17 +142,42 @@ json_pretty(PG_FUNCTION_ARGS)
}
/*
- * json_parse -- parse and validate the JSON text.
+ * json_parse -- parse a JSON text.
+ *
+ * Returns NULL if the input is not valid JSON.
+ */
+static Json *
+json_parse(const char *str, int len)
+{
+ return json_parse_or_validate(str, len, NULL);
+}
+
+/*
+ * json_validate -- validate a JSON text.
+ */
+static bool
+json_validate(const char *str, int len)
+{
+ bool valid;
+ json_parse_or_validate(str, len, &valid);
+ return valid;
+}
+
+/*
+ * Helper for json_parse and json_validate.
*
- * Only validates the input when validateOnly is true, or returns JSON
- * tree on false.
+ * If validate is NULL, this function returns a parse tree
+ * (or NULL if the JSON was invalid).
+ * If validate is not NULL, this function passes a boolean through
+ * *validate to indicate whether the JSON was valid.
*/
static Json *
-json_parse(const char *str, int len, bool validateOnly)
+json_parse_or_validate(const char *str, int len, bool *validate)
{
yyscan_t scanner;
char *scanbuf;
JsonParser parser;
+ int rc;
scanbuf = (char *) palloc(len + 2);
memcpy(scanbuf, str, len);
@@ -133,8 +185,8 @@ json_parse(const char *str, int len, bool validateOnly)
/* initialize parser and scanner */
memset(&parser, 0, sizeof(parser));
- parser.validateOnly = validateOnly;
- if (!validateOnly)
+ parser.validateOnly = !!validate;
+ if (!validate)
initStringInfo(&parser.buf);
json_yylex_init(&scanner);
@@ -142,7 +194,7 @@ json_parse(const char *str, int len, bool validateOnly)
json_yy_scan_buffer(scanbuf, len + 2, scanner);
/* parse the JSON text */
- json_yyparse(scanner);
+ rc = json_yyparse(scanner);
/* cleanup */
json_yylex_destroy(scanner);
@@ -150,6 +202,9 @@ json_parse(const char *str, int len, bool validateOnly)
if (parser.buf.data)
pfree(parser.buf.data);
+ if (validate)
+ *validate = (rc == 0);
+
return parser.json;
}
@@ -279,9 +334,7 @@ append_indent(StringInfo buf, int indent)
void
json_yyerror(yyscan_t scanner, const char *error)
{
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("syntax error in json: %s", error)));
+
}
void *
diff --git a/src/backend/utils/adt/json_scanner.l b/src/backend/utils/adt/json_scanner.l
index f4ed64f..acc0c6d 100644
--- a/src/backend/utils/adt/json_scanner.l
+++ b/src/backend/utils/adt/json_scanner.l
@@ -52,7 +52,7 @@ true { return T_JSON_TRUE; }
false { return T_JSON_FALSE; }
/* Number */
-0|-?([1-9][0-9]*(\.[0-9]+)?|0\.[0-9]+)([Ee][+-]?[0-9]+)? {
+-?(0|[1-9][0-9]*)(\.[0-9]+)?([Ee][+-]?[0-9]+)? {
JsonParser *parser = getParser();
if (!parser->validateOnly)
yylval->number = pstrdup(yytext);
@@ -66,7 +66,7 @@ false { return T_JSON_FALSE; }
if (!parser->validateOnly)
appendStringInfoString(&parser->buf, yytext);
}
-<str>([^\"\\[:cntrl:]]+|\\u[0-9A-Fa-f]{4}|\\[\"\\/bfnrt]) {
+<str>([^\"\\\x00-\x1F]+|\\u[0-9A-Fa-f]{4}|\\[\"\\/bfnrt]) {
JsonParser *parser = getParser();
if (!parser->validateOnly)
appendStringInfoString(&parser->buf, yytext);
@@ -82,7 +82,9 @@ false { return T_JSON_FALSE; }
BEGIN(INITIAL);
return T_JSON_STRING;
}
-<str>.|\n { return T_JSON_INVALID; } /* unterminated string */
+ /* unterminated string */
+<str>.|\n { return T_JSON_INVALID; }
+<str><<EOF>> { return T_JSON_INVALID; }
/* Invalid */
. return T_JSON_INVALID;
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index b3d3da5..ae49f53 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4472,6 +4472,7 @@ DATA(insert OID = 3831 ( text PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "321"
DESCR("serialize a JSON value to a character string");
DATA(insert OID = 3832 ( json_pretty PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "321" _null_ _null_ _null_ _null_ json_pretty _null_ _null_ _null_ ));
DESCR("convert a JSON to a human readable text");
+DATA(insert OID = 3833 ( json_validate PGNSP PGUID 12 1 0 0 f f f t f i 1 0 16 "25" _null_ _null_ _null_ _null_ json_validate_f _null_ _null_ _null_ ));
/* uuid */
DATA(insert OID = 2952 ( uuid_in PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2950 "2275" _null_ _null_ _null_ _null_ uuid_in _null_ _null_ _null_ ));
diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out
index 1237714..6bf7a9f 100644
--- a/src/test/regress/expected/json.out
+++ b/src/test/regress/expected/json.out
@@ -1,3 +1,365 @@
+-- Get our json_test_strings table.
+SET client_min_messages = warning;
+\set ECHO none
+RESET client_min_messages;
+-- Trivial cast-to-JSON tests
+SELECT '[]'::JSON;
+ json
+------
+ []
+(1 row)
+
+SELECT '['::JSON;
+ERROR: invalid input syntax for JSON
+LINE 1: SELECT '['::JSON;
+ ^
+SELECT '[1,2,3]'::JSON;
+ json
+---------
+ [1,2,3]
+(1 row)
+
+SELECT '[1,2,3]'::JSON::TEXT;
+ text
+---------
+ [1,2,3]
+(1 row)
+
+SELECT '[1,2,3 ]'::JSON;
+ json
+-----------
+ [1,2,3 ]
+(1 row)
+
+SELECT '[1,2,3 ,4]'::JSON;
+ json
+-------------
+ [1,2,3 ,4]
+(1 row)
+
+SELECT '[1,2,3 ,4.0]'::JSON;
+ json
+---------------
+ [1,2,3 ,4.0]
+(1 row)
+
+SELECT '[1,2,3 ,4]'::JSON;
+ json
+-------------
+ [1,2,3 ,4]
+(1 row)
+
+SELECT 'true'::JSON;
+ json
+------
+ true
+(1 row)
+
+SELECT 'true'::TEXT::JSON;
+ json
+------
+ true
+(1 row)
+
+SELECT 'false'::JSON;
+ json
+-------
+ false
+(1 row)
+
+SELECT 'null'::JSON;
+ json
+------
+ null
+(1 row)
+
+SELECT '1.1'::JSON;
+ json
+------
+ 1.1
+(1 row)
+
+SELECT '"string"'::JSON;
+ json
+----------
+ "string"
+(1 row)
+
+SELECT '{"key1":"value1", "key2":"value2"}'::JSON;
+ json
+------------------------------------
+ {"key1":"value1", "key2":"value2"}
+(1 row)
+
+SELECT '{"key1":"value1", "key2":"value2"}'::JSON;
+ json
+------------------------------------
+ {"key1":"value1", "key2":"value2"}
+(1 row)
+
+SELECT 15::JSON;
+ERROR: cannot cast type integer to json
+LINE 1: SELECT 15::JSON;
+ ^
+-- Make sure all the right strings validate
+SELECT string, json_validate(string) FROM json_test_strings;
+ string | json_validate
+----------------------------------------------------------+---------------
+ | f
+ | f
+ " | f
+ [,] | f
+ [) | f
+ []] | f
+ [} | f
+ {,} | f
+ {] | f
+ ["1":2] | f
+ [1,2,] | f
+ [1:2} | f
+ {"1":2,} | f
+ {1:2} | f
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7 ]}]} | f
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7]}]} | f
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}] | f
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]] | f
+ {"1":2, "3":4 | f
+ "1\u2" | f
+ [,2] | f
+ "3 | f
+ "3" "4" | f
+ [3[4] | f
+ [3[4]] | f
+ [3, [4, [5], 6] 7, 8 9] | f
+ [3, [4, [5], 6] 7, 8, 9] | f
+ [3, [4, [5], 6], 7, 8 9] | f
+ {"hello":true, "bye":false, null} | f
+ {"hello":true, "bye":false, null:null} | f
+ "hi | f
+ "hi""" | f
+ {"hi": "bye"] | f
+ "\uD800\uD800" | t
+ "\uD800\uDBFF" | t
+ "\UD834\UDD1E" | f
+ "\uDB00" | t
+ "\uDB00\uDBFF" | t
+ "\uFFFE" | t
+ "\uFFFF" | t
+ . | f
+ "" | t
+ [] | t
+ {} | t
+ +. | f
+ 0.5 | t
+ 0.e1 | f
+ {"1":{}} | t
+ {"1":2} | t
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"]}]} | t
+ {"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]} | t
+ 1234 | t
+ -1234 | t
+ {"1":2, "3":4} | t
+ +1234 | f
+ ++1234 | f
+ 123.456e14234 | t
+ 123.456e-14234 | t
+ 123.456e+14234 | t
+ 123.e-14234 | f
+ "1\u2000" | t
+ "1\u20001" | t
+ 2 | t
+ .246e-14234 | f
+ .2e-14234 | f
+ 3 | t
+ .3 | f
+ "3" | t
+ [3] | t
+ +3. | f
+ 3.2e+1 | t
+ [3, [4]] | t
+ [3, [4, [5]]] | t
+ [3, [4, [5], 6]] | t
+ [3, [4, [5], 6], 7] | t
+ [3, [4, [5], 6], 7, 8] | t
+ [3, [4, [5], 6], 7, 8, 9] | t
+ +3.5 | f
+ .3e | f
+ .3e1 | f
+ .3e-1 | f
+ .3e+1 | f
+ 3.e1 | f
+ 3.e+1 | f
+ 3e+1 | t
+ .5 | f
+ +.5 | f
+ .5e+1 | f
+ [ 7] | t
+ [7 ] | t
+ [7] | t
+ .e-14234 | f
+ "hello" | t
+ ["hello"] | t
+ ["hello", "bye"] | t
+ ["hello", "bye\n"] | t
+ ["hello", "bye\n\r\t"] | t
+ ["hello", "bye\n\r\t\b"] | t
+ ["hello", "bye\n\r\t\b",true] | t
+ ["hello", "bye\n\r\t\b",true , false] | t
+ ["hello", "bye\n\r\t\b",true , false, null] | t
+ ["hello", "bye\n\r\t\v"] | f
+ {"hello":true} | t
+ {"hello":true, "bye":false} | t
+ {"hello":true, "bye":false, "foo":["one","two","three"]} | t
+ "hi" | t
+ ["hi"] | t
+ ["hi", "bye"] | t
+ {"hi": "bye"} | t
+ ["hi", "bye", 3] | t
+ ["hi", "bye[", 3] | t
+ "\u0007" | t
+ "\u0008" | t
+ "\u0009" | t
+ "\u0010" | t
+ "\u0020" | t
+ "\u10000" | t
+ "\u1234" | t
+ "\u99999" | t
+ "\ud800\udc00" | t
+ "\uD800\uDC00" | t
+ "\uD834\uDD1E" | t
+ "\uDBFF\uDFFF" | t
+ "\uFFFD" | t
+ "\uFFFF" | t
+ hello | f
+ [32, 1] | t
+ [32, | f
+ "\uD800\uDC00" | t
+ "\n" | t
+ "hello" | t
+ "hello\u0009world" | t
+ "hello" | t
+ "hello\n" | t
+ "hello" | t
+ 3 | t
+ 3. | f
+ .3 | f
+ 0.3 | t
+ 0.3e | f
+ 0.3e+ | f
+ 0.3e+5 | t
+ 0.3e-5 | t
+ 0.3e5 | t
+ "hello" | t
+ +3 | f
+ -3 | t
+ -3. | f
+ -3.1 | t
+ -0 | t
+ -0. | f
+ -0.0 | t
+ .5 | f
+ 5. | f
+ 5.e1 | f
+ 0.5 | t
+ .3e1 | f
+ .3e+1 | f
+ .3e-1 | f
+ .3e-1 .5 | f
+ .3e-1.5 | f
+ .3e+1.5 | f
+ .3e+. | f
+ .3e+.5 | f
+ .3e+1.5 | f
+ 9.3e+1.5 | f
+ 9.e+1.5 | f
+ 9.e+ | f
+ 9.e+1 | f
+ "\"" | t
+ "\"3.5" | t
+ "\"." | t
+ "\".". | f
+ "\"....." | t
+ "\"\"\"\""" | f
+ "newline +| f
+ " |
+ ["\"\"\"\"", .5] | f
+ [.5] | f
+ ["\"\"\"\"", 0.5] | t
+ ["\"\"\"\"", .5] | f
+ ["\"\"\"\"",.5] | f
+ ["\"",.5] | f
+ ["\".5",.5] | f
+ ["\".5",".5\"".5] | f
+ ["\".5",".5\"", .5] | f
+ ["\".5",".5\"",.5] | f
+ ["\".5",".5\"",0.5] | t
+ {"key":/*comment*/"value"} | f
+ {"key":/*comment"value"} | f
+ {"key":"value"}/* | f
+ {"key":"value"}/**/ | f
+ {"key":"value"}/***/ | f
+ {"key":"value"}/**// | f
+ {"key":"value"}/**/// | f
+ {"key":"value"}/**///---- | f
+ {"key":"value"}# | f
+ {"key":"value"}#{ | f
+ {"key":"value"}#{} | f
+ {"key":"value"}#, | f
+ {"key":"value"/**/, "k2":"v2"} | f
+ "\u0027" | t
+ "hello\'" | f
+ 'hello\'' | f
+ 'hello' | f
+ 'hell\'o' | f
+ '\'hello' | f
+ '\'hello\'' | f
+ \'hello\' | f
+ 'hello\' | f
+ ['hello\'] | f
+ ['hello\''] | f
+ ['hello"'] | f
+ ['hello\"'] | f
+ ['hello"o'] | f
+ ['"'] | f
+ '"' | f
+ '"hello"' | f
+ '"hello' | f
+ '"hi"' | f
+ "\x01" | f
+ "\x02" | f
+ "\x03" | f
+ "\x04" | f
+ "\x05" | f
+ "\x06" | f
+ "\x07" | f
+ "\x08" | f
+ " " | f
+ " +| f
+ " |
+ "\x0B" | f
+ "\x0C" | f
+ "\r" | f
+ "\x0E" | f
+ "\x0F" | f
+ "\x10" | f
+ "\x11" | f
+ "\x12" | f
+ "\x13" | f
+ "\x14" | f
+ "\x15" | f
+ "\x16" | f
+ "\x17" | f
+ "\x18" | f
+ "\x19" | f
+ "\x1A" | f
+ "\x1B" | f
+ "\x1C" | f
+ "\x1D" | f
+ "\x1E" | f
+ "\x1F" | f
+ "\x7F" | t
+(251 rows)
+
CREATE TABLE jsontest (
id int,
data json
@@ -6,15 +368,15 @@ INSERT INTO jsontest VALUES (1, 'null');
INSERT INTO jsontest VALUES (2, '{"booleans":[true,false],"null":null}');
INSERT INTO jsontest VALUES (3, E'[\n123.456,\n"string",\n{"name":"object"}\n]');
INSERT INTO jsontest VALUES (101, 'wrong');
-ERROR: syntax error in json: syntax error
+ERROR: invalid input syntax for JSON
LINE 1: INSERT INTO jsontest VALUES (101, 'wrong');
^
INSERT INTO jsontest VALUES (101, '[wrong');
-ERROR: syntax error in json: syntax error
+ERROR: invalid input syntax for JSON
LINE 1: INSERT INTO jsontest VALUES (101, '[wrong');
^
INSERT INTO jsontest VALUES (101, '{"wrong":123}}');
-ERROR: syntax error in json: syntax error
+ERROR: invalid input syntax for JSON
LINE 1: INSERT INTO jsontest VALUES (101, '{"wrong":123}}');
^
SELECT *, json_pretty(data) FROM jsontest;
diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql
index 76a1d06..841052d 100644
--- a/src/test/regress/sql/json.sql
+++ b/src/test/regress/sql/json.sql
@@ -1,3 +1,32 @@
+-- Get our json_test_strings table.
+SET client_min_messages = warning;
+\set ECHO none
+\i sql/json_test_strings.sql
+\set ECHO all
+RESET client_min_messages;
+
+-- Trivial cast-to-JSON tests
+SELECT '[]'::JSON;
+SELECT '['::JSON;
+SELECT '[1,2,3]'::JSON;
+SELECT '[1,2,3]'::JSON::TEXT;
+SELECT '[1,2,3 ]'::JSON;
+SELECT '[1,2,3 ,4]'::JSON;
+SELECT '[1,2,3 ,4.0]'::JSON;
+SELECT '[1,2,3 ,4]'::JSON;
+SELECT 'true'::JSON;
+SELECT 'true'::TEXT::JSON;
+SELECT 'false'::JSON;
+SELECT 'null'::JSON;
+SELECT '1.1'::JSON;
+SELECT '"string"'::JSON;
+SELECT '{"key1":"value1", "key2":"value2"}'::JSON;
+SELECT '{"key1":"value1", "key2":"value2"}'::JSON;
+SELECT 15::JSON;
+
+-- Make sure all the right strings validate
+SELECT string, json_validate(string) FROM json_test_strings;
+
CREATE TABLE jsontest (
id int,
data json
diff --git a/src/test/regress/sql/json_test_strings.sql b/src/test/regress/sql/json_test_strings.sql
new file mode 100644
index 0000000..909a0da
--- /dev/null
+++ b/src/test/regress/sql/json_test_strings.sql
@@ -0,0 +1,264 @@
+/*
+ * This is not a test. It is the set of
+ * test strings used by the json.sql test.
+ */
+
+CREATE TABLE json_test_strings (string TEXT);
+INSERT INTO json_test_strings VALUES ($$$$);
+INSERT INTO json_test_strings VALUES ($$ $$);
+INSERT INTO json_test_strings VALUES ($$"$$);
+INSERT INTO json_test_strings VALUES ($$[,]$$);
+INSERT INTO json_test_strings VALUES ($$[)$$);
+INSERT INTO json_test_strings VALUES ($$[]]$$);
+INSERT INTO json_test_strings VALUES ($$[}$$);
+INSERT INTO json_test_strings VALUES ($${,}$$);
+INSERT INTO json_test_strings VALUES ($${]$$);
+INSERT INTO json_test_strings VALUES ($$["1":2]$$);
+INSERT INTO json_test_strings VALUES ($$[1,2,]$$);
+INSERT INTO json_test_strings VALUES ($$[1:2}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2,}$$);
+INSERT INTO json_test_strings VALUES ($${1:2}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7 ]}]}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7]}]}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]]$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "3":4$$);
+INSERT INTO json_test_strings VALUES ($$"1\u2"$$);
+INSERT INTO json_test_strings VALUES ($$[,2]$$);
+INSERT INTO json_test_strings VALUES ($$"3$$);
+INSERT INTO json_test_strings VALUES ($$"3" "4"$$);
+INSERT INTO json_test_strings VALUES ($$[3[4]$$);
+INSERT INTO json_test_strings VALUES ($$[3[4]]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6] 7, 8 9]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6] 7, 8, 9]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6], 7, 8 9]$$);
+INSERT INTO json_test_strings VALUES ($${"hello":true, "bye":false, null}$$);
+INSERT INTO json_test_strings VALUES ($${"hello":true, "bye":false, null:null}$$);
+INSERT INTO json_test_strings VALUES ($$"hi$$);
+INSERT INTO json_test_strings VALUES ($$"hi"""$$);
+INSERT INTO json_test_strings VALUES ($${"hi": "bye"]$$);
+INSERT INTO json_test_strings VALUES ($$"\uD800\uD800"$$);
+INSERT INTO json_test_strings VALUES ($$"\uD800\uDBFF"$$);
+INSERT INTO json_test_strings VALUES ($$"\UD834\UDD1E"$$);
+INSERT INTO json_test_strings VALUES ($$"\uDB00"$$);
+INSERT INTO json_test_strings VALUES ($$"\uDB00\uDBFF"$$);
+INSERT INTO json_test_strings VALUES ($$"\uFFFE"$$);
+INSERT INTO json_test_strings VALUES ($$"\uFFFF"$$);
+INSERT INTO json_test_strings VALUES ($$.$$);
+INSERT INTO json_test_strings VALUES ($$""$$);
+INSERT INTO json_test_strings VALUES ($$[]$$);
+INSERT INTO json_test_strings VALUES ($${}$$);
+INSERT INTO json_test_strings VALUES ($$+.$$);
+INSERT INTO json_test_strings VALUES ($$0.5$$);
+INSERT INTO json_test_strings VALUES ($$0.e1$$);
+INSERT INTO json_test_strings VALUES ($${"1":{}}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"]}]}$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]}$$);
+INSERT INTO json_test_strings VALUES ($$1234$$);
+INSERT INTO json_test_strings VALUES ($$-1234$$);
+INSERT INTO json_test_strings VALUES ($${"1":2, "3":4}$$);
+INSERT INTO json_test_strings VALUES ($$+1234$$);
+INSERT INTO json_test_strings VALUES ($$++1234$$);
+INSERT INTO json_test_strings VALUES ($$123.456e14234$$);
+INSERT INTO json_test_strings VALUES ($$123.456e-14234$$);
+INSERT INTO json_test_strings VALUES ($$123.456e+14234$$);
+INSERT INTO json_test_strings VALUES ($$123.e-14234$$);
+INSERT INTO json_test_strings VALUES ($$"1\u2000"$$);
+INSERT INTO json_test_strings VALUES ($$"1\u20001"$$);
+INSERT INTO json_test_strings VALUES ($$2$$);
+INSERT INTO json_test_strings VALUES ($$.246e-14234$$);
+INSERT INTO json_test_strings VALUES ($$.2e-14234$$);
+INSERT INTO json_test_strings VALUES ($$3$$);
+INSERT INTO json_test_strings VALUES ($$.3$$);
+INSERT INTO json_test_strings VALUES ($$"3"$$);
+INSERT INTO json_test_strings VALUES ($$[3]$$);
+INSERT INTO json_test_strings VALUES ($$+3.$$);
+INSERT INTO json_test_strings VALUES ($$3.2e+1$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4]]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5]]]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6]]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6], 7]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6], 7, 8]$$);
+INSERT INTO json_test_strings VALUES ($$[3, [4, [5], 6], 7, 8, 9]$$);
+INSERT INTO json_test_strings VALUES ($$+3.5$$);
+INSERT INTO json_test_strings VALUES ($$.3e$$);
+INSERT INTO json_test_strings VALUES ($$.3e1$$);
+INSERT INTO json_test_strings VALUES ($$.3e-1$$);
+INSERT INTO json_test_strings VALUES ($$.3e+1$$);
+INSERT INTO json_test_strings VALUES ($$3.e1$$);
+INSERT INTO json_test_strings VALUES ($$3.e+1$$);
+INSERT INTO json_test_strings VALUES ($$3e+1$$);
+INSERT INTO json_test_strings VALUES ($$.5$$);
+INSERT INTO json_test_strings VALUES ($$+.5$$);
+INSERT INTO json_test_strings VALUES ($$.5e+1$$);
+INSERT INTO json_test_strings VALUES ($$[ 7]$$);
+INSERT INTO json_test_strings VALUES ($$[7 ]$$);
+INSERT INTO json_test_strings VALUES ($$[7]$$);
+INSERT INTO json_test_strings VALUES ($$.e-14234$$);
+INSERT INTO json_test_strings VALUES ($$"hello"$$);
+INSERT INTO json_test_strings VALUES ($$["hello"]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye"]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n"]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t"]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t\b"]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t\b",true]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t\b",true , false]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t\b",true , false, null]$$);
+INSERT INTO json_test_strings VALUES ($$["hello", "bye\n\r\t\v"]$$);
+INSERT INTO json_test_strings VALUES ($${"hello":true}$$);
+INSERT INTO json_test_strings VALUES ($${"hello":true, "bye":false}$$);
+INSERT INTO json_test_strings VALUES ($${"hello":true, "bye":false, "foo":["one","two","three"]}$$);
+INSERT INTO json_test_strings VALUES ($$"hi"$$);
+INSERT INTO json_test_strings VALUES ($$["hi"]$$);
+INSERT INTO json_test_strings VALUES ($$["hi", "bye"]$$);
+INSERT INTO json_test_strings VALUES ($${"hi": "bye"}$$);
+INSERT INTO json_test_strings VALUES ($$["hi", "bye", 3]$$);
+INSERT INTO json_test_strings VALUES ($$["hi", "bye[", 3]$$);
+INSERT INTO json_test_strings VALUES ($$"\u0007"$$);
+INSERT INTO json_test_strings VALUES ($$"\u0008"$$);
+INSERT INTO json_test_strings VALUES ($$"\u0009"$$);
+INSERT INTO json_test_strings VALUES ($$"\u0010"$$);
+INSERT INTO json_test_strings VALUES ($$"\u0020"$$);
+INSERT INTO json_test_strings VALUES ($$"\u10000"$$);
+INSERT INTO json_test_strings VALUES ($$"\u1234"$$);
+INSERT INTO json_test_strings VALUES ($$"\u99999"$$);
+INSERT INTO json_test_strings VALUES ($$"\ud800\udc00"$$);
+INSERT INTO json_test_strings VALUES ($$"\uD800\uDC00"$$);
+INSERT INTO json_test_strings VALUES ($$"\uD834\uDD1E"$$);
+INSERT INTO json_test_strings VALUES ($$"\uDBFF\uDFFF"$$);
+INSERT INTO json_test_strings VALUES ($$"\uFFFD"$$);
+INSERT INTO json_test_strings VALUES ($$"\uFFFF"$$);
+INSERT INTO json_test_strings VALUES ($$hello$$);
+INSERT INTO json_test_strings VALUES ($$[32, 1]$$);
+INSERT INTO json_test_strings VALUES ($$[32, $$);
+INSERT INTO json_test_strings VALUES ($$"\uD800\uDC00"$$);
+INSERT INTO json_test_strings VALUES ($$"\n"$$);
+INSERT INTO json_test_strings VALUES ($$"hello"$$);
+INSERT INTO json_test_strings VALUES ($$"hello\u0009world"$$);
+INSERT INTO json_test_strings VALUES ($$"hello"$$);
+INSERT INTO json_test_strings VALUES ($$"hello\n"$$);
+INSERT INTO json_test_strings VALUES ($$"hello"$$);
+INSERT INTO json_test_strings VALUES ($$3$$);
+INSERT INTO json_test_strings VALUES ($$3.$$);
+INSERT INTO json_test_strings VALUES ($$.3$$);
+INSERT INTO json_test_strings VALUES ($$0.3$$);
+INSERT INTO json_test_strings VALUES ($$0.3e$$);
+INSERT INTO json_test_strings VALUES ($$0.3e+$$);
+INSERT INTO json_test_strings VALUES ($$0.3e+5$$);
+INSERT INTO json_test_strings VALUES ($$0.3e-5$$);
+INSERT INTO json_test_strings VALUES ($$0.3e5$$);
+INSERT INTO json_test_strings VALUES ($$"hello"$$);
+INSERT INTO json_test_strings VALUES ($$+3$$);
+INSERT INTO json_test_strings VALUES ($$-3$$);
+INSERT INTO json_test_strings VALUES ($$-3.$$);
+INSERT INTO json_test_strings VALUES ($$-3.1$$);
+INSERT INTO json_test_strings VALUES ($$-0$$);
+INSERT INTO json_test_strings VALUES ($$-0.$$);
+INSERT INTO json_test_strings VALUES ($$-0.0$$);
+INSERT INTO json_test_strings VALUES ($$.5$$);
+INSERT INTO json_test_strings VALUES ($$5.$$);
+INSERT INTO json_test_strings VALUES ($$5.e1$$);
+INSERT INTO json_test_strings VALUES ($$0.5$$);
+INSERT INTO json_test_strings VALUES ($$.3e1$$);
+INSERT INTO json_test_strings VALUES ($$.3e+1$$);
+INSERT INTO json_test_strings VALUES ($$.3e-1$$);
+INSERT INTO json_test_strings VALUES ($$.3e-1 .5$$);
+INSERT INTO json_test_strings VALUES ($$.3e-1.5$$);
+INSERT INTO json_test_strings VALUES ($$.3e+1.5$$);
+INSERT INTO json_test_strings VALUES ($$.3e+.$$);
+INSERT INTO json_test_strings VALUES ($$.3e+.5$$);
+INSERT INTO json_test_strings VALUES ($$.3e+1.5$$);
+INSERT INTO json_test_strings VALUES ($$9.3e+1.5$$);
+INSERT INTO json_test_strings VALUES ($$9.e+1.5$$);
+INSERT INTO json_test_strings VALUES ($$9.e+$$);
+INSERT INTO json_test_strings VALUES ($$9.e+1$$);
+INSERT INTO json_test_strings VALUES ($$"\""$$);
+INSERT INTO json_test_strings VALUES ($$"\"3.5"$$);
+INSERT INTO json_test_strings VALUES ($$"\"."$$);
+INSERT INTO json_test_strings VALUES ($$"\".".$$);
+INSERT INTO json_test_strings VALUES ($$"\"....."$$);
+INSERT INTO json_test_strings VALUES ($$"\"\"\"\"""$$);
+INSERT INTO json_test_strings VALUES (E'"newline\n"');
+INSERT INTO json_test_strings VALUES ($$["\"\"\"\"", .5]$$);
+INSERT INTO json_test_strings VALUES ($$[.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\"\"\"\"", 0.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\"\"\"\"", .5]$$);
+INSERT INTO json_test_strings VALUES ($$["\"\"\"\"",.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\"",.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\".5",.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\".5",".5\"".5]$$);
+INSERT INTO json_test_strings VALUES ($$["\".5",".5\"", .5]$$);
+INSERT INTO json_test_strings VALUES ($$["\".5",".5\"",.5]$$);
+INSERT INTO json_test_strings VALUES ($$["\".5",".5\"",0.5]$$);
+INSERT INTO json_test_strings VALUES ($${"key":/*comment*/"value"}$$);
+INSERT INTO json_test_strings VALUES ($${"key":/*comment"value"}$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/*$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/**/$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/***/$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/**//$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/**///$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}/**///----$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}#$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}#{$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}#{}$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"}#,$$);
+INSERT INTO json_test_strings VALUES ($${"key":"value"/**/, "k2":"v2"}$$);
+INSERT INTO json_test_strings VALUES ($$"\u0027"$$);
+INSERT INTO json_test_strings VALUES ($$"hello\'"$$);
+INSERT INTO json_test_strings VALUES ($$'hello\''$$);
+INSERT INTO json_test_strings VALUES ($$'hello'$$);
+INSERT INTO json_test_strings VALUES ($$'hell\'o'$$);
+INSERT INTO json_test_strings VALUES ($$'\'hello'$$);
+INSERT INTO json_test_strings VALUES ($$'\'hello\''$$);
+INSERT INTO json_test_strings VALUES ($$\'hello\'$$);
+INSERT INTO json_test_strings VALUES ($$'hello\'$$);
+INSERT INTO json_test_strings VALUES ($$['hello\']$$);
+INSERT INTO json_test_strings VALUES ($$['hello\'']$$);
+INSERT INTO json_test_strings VALUES ($$['hello"']$$);
+INSERT INTO json_test_strings VALUES ($$['hello\"']$$);
+INSERT INTO json_test_strings VALUES ($$['hello"o']$$);
+INSERT INTO json_test_strings VALUES ($$['"']$$);
+INSERT INTO json_test_strings VALUES ($$'"'$$);
+INSERT INTO json_test_strings VALUES ($$'"hello"'$$);
+INSERT INTO json_test_strings VALUES ($$'"hello'$$);
+INSERT INTO json_test_strings VALUES ($$'"hi"'$$);
+
+-- Control characters not allowed in JSON strings.
+-- Can't test \x00 because it's not even a valid TEXT.
+INSERT INTO json_test_strings VALUES (E'"\x01"');
+INSERT INTO json_test_strings VALUES (E'"\x02"');
+INSERT INTO json_test_strings VALUES (E'"\x03"');
+INSERT INTO json_test_strings VALUES (E'"\x04"');
+INSERT INTO json_test_strings VALUES (E'"\x05"');
+INSERT INTO json_test_strings VALUES (E'"\x06"');
+INSERT INTO json_test_strings VALUES (E'"\x07"');
+INSERT INTO json_test_strings VALUES (E'"\x08"');
+INSERT INTO json_test_strings VALUES (E'"\x09"');
+INSERT INTO json_test_strings VALUES (E'"\x0A"');
+INSERT INTO json_test_strings VALUES (E'"\x0B"');
+INSERT INTO json_test_strings VALUES (E'"\x0C"');
+INSERT INTO json_test_strings VALUES (E'"\x0D"');
+INSERT INTO json_test_strings VALUES (E'"\x0E"');
+INSERT INTO json_test_strings VALUES (E'"\x0F"');
+INSERT INTO json_test_strings VALUES (E'"\x10"');
+INSERT INTO json_test_strings VALUES (E'"\x11"');
+INSERT INTO json_test_strings VALUES (E'"\x12"');
+INSERT INTO json_test_strings VALUES (E'"\x13"');
+INSERT INTO json_test_strings VALUES (E'"\x14"');
+INSERT INTO json_test_strings VALUES (E'"\x15"');
+INSERT INTO json_test_strings VALUES (E'"\x16"');
+INSERT INTO json_test_strings VALUES (E'"\x17"');
+INSERT INTO json_test_strings VALUES (E'"\x18"');
+INSERT INTO json_test_strings VALUES (E'"\x19"');
+INSERT INTO json_test_strings VALUES (E'"\x1A"');
+INSERT INTO json_test_strings VALUES (E'"\x1B"');
+INSERT INTO json_test_strings VALUES (E'"\x1C"');
+INSERT INTO json_test_strings VALUES (E'"\x1D"');
+INSERT INTO json_test_strings VALUES (E'"\x1E"');
+INSERT INTO json_test_strings VALUES (E'"\x1F"');
+
+-- Although \x7F is a control character, the JSON RFC only says
+-- "..., and the control characters (U+0000 through U+001F)".
+-- However, whether to trust the RFC here or not is a tough call.
+INSERT INTO json_test_strings VALUES (E'"\x7F"');