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

时间:2015-04-25 19:53:00

标签: json postgresql

创建JSON导出时,Postgres错误地引用了引号。请注意以下更新中的双引号...

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';

output.json的内容:

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

您可以看到引号未正确转义,并且会创建无效的JSON。 它应该是:

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

如何解决这个Postgres错误或解决它?

2 个答案:

答案 0 :(得分:11)

这与JSON无关。它是关于COPY命令中文本格式(默认)处理反斜杠的方式。来自the PostgreSQL documentation - COPY

  

反斜杠字符(\)可以在COPY数据中用于引用可能被视为行或列分隔符的数据字符。特别是,如果以下字符作为列值的一部分出现,则必须以反斜杠开头:反斜杠本身,换行符,回车符和当前分隔符。

(强调我的。)
您可以使用CSV格式并将引号字符从doublequote更改为其他内容来解决它。

演示:

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\""} |

答案 1 :(得分:3)

如果您确定角色$或您选择的特殊引号字符出现在您的字符串中,则SimoKivistö的答案有效。在我的情况下,我必须导出一个非常大的表,并且没有特殊的字符没有出现在字符串中。

要解决此问题,我将COPY命令的输出传送到sed以恢复引号的双重转义:

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

我正在管道的sed表达式只是用\\"替换\"的出现次数。