2015-04-25 36 views
5

創建JSON導出時,Postgres不正確地轉義引號。注意雙引號在下面的更新中...Postgres row_to_json產生無效的JSON和雙重轉義引號

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的錯誤或解決它?

+0

我將此作爲bug#13160提交給http://www.postgresql.org/list/pgsql-bugs/(待審覈) –

+0

這不是一個錯誤。 'COPY'不用於將單個結果輸出到文件。它發出逃逸的面向行的數據。這聽起來像你想'psql'的'\ o'選項。 –

回答

7

這不是JSON相關的。這是關於COPY命令中文本格式(默認)處理反斜槓的方式。從the PostgreSQL documentation - COPY

反斜線字符(\)可在COPY數據被用於引用否則可能被視爲行或列分隔符數據的字符。特別是,如果以下字符作爲列值的一部分顯示,則必須在前面加上反斜槓:反斜槓本身,換行符,回車符和當前分隔符。

(重點煤礦。)
您可以通過使用CSV格式和改變引號字符的雙引號到別的解決它。

爲了證明:

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

你能解釋一下你的建議解決方案嗎? –

+1

解決方案在第三行:'COPY(SELECT row_to_json(row('「hello」')))TO'/output.json'CSV QUOTE'$';'唯一添加到不工作的版本上上一行是'CSV QUOTE'$''。與默認文本格式不同,此更改爲CSV格式,不會將第二個反斜槓添加到反斜槓。在CSV中,默認引用字符是雙引號,因此必須更改爲其他內容 - 本示例中的美元符號。 –

+0

但這並不意味着我可能在我的字符串中會出現任何美元符號會被反斜槓轉義?我正在導出一張大桌子,實際上沒有任何特殊角色不會100%確定地出現。不知何故,可以逃脫只是被禁用? –

2

通過廝磨Kivistö答案工作,如果你有一定的文字$,或任何特殊報價你選擇的字符是不會出現在您的字符串中。就我而言,我不得不導出一張非常大的表格,並且沒有沒有出現在字符串中的特定字符。

要解決這個問題,我用管道輸送的COPY命令的輸出sed恢復報價的雙重轉義:

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

sed表達我的管道簡單地取代了\\"出現與\"

+0

我用一個稍微不同的sed食譜取得了成功:用單個反斜槓替換了所有的反斜槓對:'sed's/\\\\/\\/g''。 –

+0

在新版本的Postgres中(自9.3以來我相信),你也可以在COPY語句中加入一個過濾器,例如'COPY(從my_table中選擇row_to_json(t)作爲t)TO PROGRAM $$ sed's/\\\\/\\/g'> my_table.json $$' –