File tree 7 files changed +77
-7
lines changed
7 files changed +77
-7
lines changed Original file line number Diff line number Diff line change 180
180
</para>
181
181
</listitem>
182
182
183
+ <listitem>
184
+ <para>
185
+ Unicode escapes in <link linkend="datatype-json"><type>JSON</type></link>
186
+ text values are no longer rendered with the backslash escaped.
187
+ (Andrew Dunstan)
188
+ </para>
189
+
190
+ <para>
191
+ Previously all backslashes in text values being formed into JSON were
192
+ escaped. Now a backslash followed by "u" and four hexadecimal digits is
193
+ not escaped, as this is a legal sequence in a JSON string value, and
194
+ escaping the backslash led to some perverse results.
195
+ </para>
196
+ </listitem>
197
+
183
198
<listitem>
184
199
<para>
185
200
Rename <link linkend="SQL-EXPLAIN"><command>EXPLAIN
Original file line number Diff line number Diff line change @@ -2315,7 +2315,26 @@ escape_json(StringInfo buf, const char *str)
2315
2315
appendStringInfoString (buf , "\\\"" );
2316
2316
break ;
2317
2317
case '\\' :
2318
- appendStringInfoString (buf , "\\\\" );
2318
+ /*
2319
+ * Unicode escapes are passed through as is. There is no
2320
+ * requirement that they denote a valid character in the
2321
+ * server encoding - indeed that is a big part of their
2322
+ * usefulness.
2323
+ *
2324
+ * All we require is that they consist of \uXXXX where
2325
+ * the Xs are hexadecimal digits. It is the responsibility
2326
+ * of the caller of, say, to_json() to make sure that the
2327
+ * unicode escape is valid.
2328
+ *
2329
+ * In the case of a jsonb string value being escaped, the
2330
+ * only unicode escape that should be present is \u0000,
2331
+ * all the other unicode escapes will have been resolved.
2332
+ */
2333
+ if (p [1 ] == 'u' && isxdigit (p [2 ]) && isxdigit (p [3 ])
2334
+ && isxdigit (p [4 ]) && isxdigit (p [5 ]))
2335
+ appendStringInfoCharMacro (buf , * p );
2336
+ else
2337
+ appendStringInfoString (buf , "\\\\" );
2319
2338
break ;
2320
2339
default :
2321
2340
if ((unsigned char ) * p < ' ' )
Original file line number Diff line number Diff line change @@ -426,6 +426,20 @@ select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
426
426
(1 row)
427
427
428
428
COMMIT;
429
+ -- unicode escape - backslash is not escaped
430
+ select to_json(text '\uabcd');
431
+ to_json
432
+ ----------
433
+ "\uabcd"
434
+ (1 row)
435
+
436
+ -- any other backslash is escaped
437
+ select to_json(text '\abcd');
438
+ to_json
439
+ ----------
440
+ "\\abcd"
441
+ (1 row)
442
+
429
443
--json_agg
430
444
SELECT json_agg(q)
431
445
FROM ( SELECT $$a$$ || x AS b, y AS c,
Original file line number Diff line number Diff line change @@ -426,6 +426,20 @@ select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
426
426
(1 row)
427
427
428
428
COMMIT;
429
+ -- unicode escape - backslash is not escaped
430
+ select to_json(text '\uabcd');
431
+ to_json
432
+ ----------
433
+ "\uabcd"
434
+ (1 row)
435
+
436
+ -- any other backslash is escaped
437
+ select to_json(text '\abcd');
438
+ to_json
439
+ ----------
440
+ "\\abcd"
441
+ (1 row)
442
+
429
443
--json_agg
430
444
SELECT json_agg(q)
431
445
FROM ( SELECT $$a$$ || x AS b, y AS c,
Original file line number Diff line number Diff line change @@ -61,9 +61,9 @@ LINE 1: SELECT '"\u000g"'::jsonb;
61
61
DETAIL: "\u" must be followed by four hexadecimal digits.
62
62
CONTEXT: JSON data, line 1: "\u000g...
63
63
SELECT '"\u0000"'::jsonb; -- OK, legal escape
64
- jsonb
65
- -----------
66
- "\\ u0000"
64
+ jsonb
65
+ ----------
66
+ "\u0000"
67
67
(1 row)
68
68
69
69
-- use octet_length here so we don't get an odd unicode char in the
Original file line number Diff line number Diff line change @@ -61,9 +61,9 @@ LINE 1: SELECT '"\u000g"'::jsonb;
61
61
DETAIL: "\u" must be followed by four hexadecimal digits.
62
62
CONTEXT: JSON data, line 1: "\u000g...
63
63
SELECT '"\u0000"'::jsonb; -- OK, legal escape
64
- jsonb
65
- -----------
66
- "\\ u0000"
64
+ jsonb
65
+ ----------
66
+ "\u0000"
67
67
(1 row)
68
68
69
69
-- use octet_length here so we don't get an odd unicode char in the
Original file line number Diff line number Diff line change @@ -111,6 +111,14 @@ SET LOCAL TIME ZONE -8;
111
111
select to_json(timestamptz ' 2014-05-28 12:22:35.614298-04' );
112
112
COMMIT ;
113
113
114
+ -- unicode escape - backslash is not escaped
115
+
116
+ select to_json(text ' \u abcd' );
117
+
118
+ -- any other backslash is escaped
119
+
120
+ select to_json(text ' \a bcd' );
121
+
114
122
-- json_agg
115
123
116
124
SELECT json_agg(q)
You can’t perform that action at this time.
0 commit comments