简体   繁体   English

Postgres row_to_json 生成带有双转义引号的无效 JSON

[英]Postgres row_to_json produces invalid JSON with double escaped quotes

Postgres escapes quotes incorrectly when creating a JSON export. Postgres 在创建 JSON 导出时错误地转义引号。 Note the double quotes in the below update...请注意以下更新中的双引号...

UPDATE models SET column='"hello"' WHERE id=1;

COPY (SELECT row_to_json(models)
    FROM (SELECT column FROM shaders WHERE id=1) shaders)
    TO '/output.json';

The contents of output.json: output.json 的内容:

{"column":"\\"hello\\""}

You can see that the quotes are escaped improperly and it creates invalid JSON.您可以看到引号被错误地转义并创建了无效的 JSON。 It should be:它应该是:

{"column":"\"hello\""}

How can I fix this Postgres bug or work around it?如何修复这个 Postgres 错误或解决它?

This is not JSON related.这与 JSON 无关。 It's about the way text format (default) in COPY command handles backslashes.这是关于COPY命令中的文本格式(默认)处理反斜杠的方式。 From the PostgreSQL documentation - COPY :PostgreSQL 文档 - COPY

Backslash characters ( \\ ) can be used in the COPY data to quote data characters that might otherwise be taken as row or column delimiters.可以在 COPY 数据中使用反斜杠字符 ( \\ ) 来引用可能被视为行或列分隔符的数据字符。 In particular, the following characters must be preceded by a backslash if they appear as part of a column value: backslash itself , newline, carriage return, and the current delimiter character.特别是,如果以下字符作为列值的一部分出现,则必须在其前面加上反斜杠:反斜杠本身、换行符、回车符和当前分隔符。

(Emphasis mine.) (强调我的。)
You can solve it by using CSV-format and changing the quote character from doublequote to something else.您可以通过使用 CSV 格式并将引号字符从双引号更改为其他内容来解决它。

To demonstrate:展示:

SELECT row_to_json(row('"hello"'))
 | "{"f1":"\"hello\""}" |


COPY (SELECT row_to_json(row('"hello"'))) TO '/output.json';
 | {"f1":"\\"hello\\""} |


COPY (SELECT row_to_json(row('"hello"'))) TO '/output.json' CSV QUOTE '$';
 | {"f1":"\"hello\""} |

The answer by Simo Kivistö works if you are certain that the character $ , or whatever the special quote character you chose does not appear in your strings.如果您确定字符$或您选择的任何特殊引号字符没有出现在您的字符串中,那么 Simo Kivistö 的答案就有效。 In my case, I had to export a very large table and there was no particular character which didn't appear in the strings.就我而言,我必须导出一个非常大的表,并且没有出现在字符串中的特定字符。

To work around this issue, I piped the output of the COPY command to sed to revert the double escaping of quotes:为了解决这个问题,我将COPY命令的输出通过管道传送到sed以恢复引号的双重转义:

psql -c "COPY (SELECT row_to_json(t) from my_table as t) to STDOUT;" |
  sed 's/\\"/\"/g' > my_table.json

The sed expression I am piping to simply replaces occurrences of \\\\" with \\" .我正在传递的sed表达式只是将\\\\"出现替换为\\"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM