2015-04-25 18 views
5

Postgres gibt beim Erstellen eines JSON-Exports falsche Anführungszeichen zurück. Beachten Sie die Anführungszeichen in das unten stehende Update ...Postgres row_to_json erzeugt ungültiges JSON mit doppelten Escape-Anführungszeichen

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

Der Inhalt output.json:

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

Sie können sehen, dass die Zitate nicht richtig entkommen sind und es schafft ungültige JSON. Es sollte sein:

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

Wie kann ich diesen Postgres Fehler oder Arbeit um das Problem beheben?

+0

Ich reichte dies als Fehler # 13160 zu http://www.postgresql.org/list/pgsql-bugs/ (ausstehende Moderation) –

+0

Es ist kein Fehler. Mit 'COPY' können keine einzelnen Ergebnisse in eine Datei ausgegeben werden. Es gibt ausgeblendete zeilenorientierte Daten aus. Es klingt, als würdest du stattdessen 'psql's' \ o' Option haben. –

Antwort

7

Dies ist nicht mit JSON verbunden. Es geht um die Art, wie das Textformat (Standard) in COPY Befehl Backslashes behandelt. Von the PostgreSQL documentation - COPY:

Aufkantung Zeichen (\) in den COPY-Daten verwendet werden, um Datenzeichen zu zitieren, die sonst als Zeilen- oder Spaltentrennzeichen genommen werden könnten. Insbesondere müssen die folgenden Zeichen durch einen umgekehrten Schrägstrich gekennzeichnet werden, wenn sie als Teil eines Spaltenwerts angezeigt werden: Backslash selbst, Zeilenumbruch, Wagenrücklauf und das aktuelle Trennzeichen.

(Hervorhebung von mir.)
Sie können es lösen, indem CSV-Format und die Anführungszeichen von double, um etwas anderes zu ändern.

Um zu demonstrieren:

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

Können Sie erklären, was Ihre vorgeschlagene Lösung dort macht? –

+1

Die Lösung ist in der dritten Zeile: 'COPY (SELECT row_to_json (row ('" hallo "')) TO '/output.json' CSV QUOTE '$';' und das einzige, was zu der nicht funktionierenden Version hinzugefügt Die vorherige Zeile ist 'CSV QUOTE '$''.Dies ändert sich in das CSV-Format, das Backslashes im Gegensatz zum Standardtextformat keinen umgekehrten Schrägstrich hinzufügt. In CSV ist das Standard-Anführungszeichen ein Anführungszeichen, das in etwas anderem geändert werden muss - in diesem Beispiel ein Dollarzeichen. –

+0

aber bedeutet das nicht, dass irgendwelche Dollarzeichen, die ich in meinen Strings haben kann, mit einem umgekehrten Schrägstrich entkommen werden? Ich exportiere eine große Tabelle und es gibt tatsächlich kein bestimmtes Zeichen, das nicht mit 100% Sicherheit erscheint. Kann die Flucht irgendwie einfach deaktiviert werden? –

2

Die Antwort von Simo Kivistö funktioniert, wenn Sie sicher sind, dass der Charakter $, oder was auch immer das besondere Angebot Zeichen, das Sie gewählt haben erscheint nicht in Ihren Strings. In meinem Fall musste ich eine sehr große Tabelle exportieren und es gab kein bestimmtes Zeichen, das nicht in den Strings erschien.

, um dieses Problem zu umgehen, verrohrt ich den Ausgang des COPY Befehl sed die doppelte Entkommen von Zitaten zurückzukehren:

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

Der sed Ausdruck I Rohr bin einfach Vorkommen von \\" mit \" ersetzt.

+0

Ich hatte Erfolg mit einem etwas anderen sed Rezept: Ersetzen Sie alle Backslash-Paare mit einzelnen Backslash: 'sed 's/\\\\/\\/g''. –

+0

In neueren Versionen von Postgres (seit 9.3 glaube ich), können Sie auch einen Filter in die COPY-Anweisung einfügen, wie 'COPY (SELECT row_to_json (t) von my_table als t) TO PROGRAM $$ sed 's/\\\\/\\/g '> mein_table.json $$ ' –

Verwandte Themen