2015-04-25 9 views
5

Postgres sfugge erroneamente le offerte quando si crea un'esportazione JSON. Si notino le virgolette doppie nell'aggiornamento di seguito ...Postgres row_to_json produce JSON non valido con citazioni con doppio escape

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

Il contenuto di output.json:

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

Si può vedere che le citazioni sono fuggiti in modo improprio e crea JSON valido. Dovrebbe essere:

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

Come posso risolvere questo bug Postgres o di lavoro intorno ad esso?

+0

Ho inviato questo come bug # 13160 a http://www.postgresql.org/list/pgsql-bugs/ (moderazione in attesa) –

+0

Non è un bug. 'COPY' non è l'output di singoli risultati in un file. Emette i dati orientati alla fila in escape. Sembra che tu voglia invece l'opzione '\ o' di' psql'. –

risposta

7

Questo non è correlato a JSON. Riguarda il modo in cui il formato testo (predefinito) nel comando COPY gestisce i backslash. Da the PostgreSQL documentation - COPY:

caratteri rovesciati (\) possono essere utilizzati nei dati COPIA citare caratteri di dati che altrimenti potrebbero essere prese come delimitatori di riga o colonna. In particolare, i seguenti caratteri devono essere preceduti da una barra rovesciata se appaiono come parte di un valore di colonna: backslash stesso, newline, ritorno a capo e il carattere delimitatore corrente.

(sottolineatura mia).
si può risolvere utilizzando formato CSV e cambiando il carattere di citazione da doublequote a qualcos'altro.

Per dimostrare:

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

Puoi spiegare cosa ci fa la tua soluzione suggerita? –

+1

La soluzione è nella terza riga: 'COPY (SELECT row_to_json (row ('" hello "'))) TO '/output.json' CSV QUOTE '$';' e l'unica cosa aggiunta alla versione non funzionante su la riga precedente è 'CSV QUOTE '$''.Questo cambia in formato CSV che non aggiunge la seconda barra retroversa alle barre retroverse a differenza del formato di testo predefinito. In CSV il carattere di virgolette predefinito è double quote, quindi è necessario cambiarlo in qualcos'altro: il simbolo del dollaro in questo esempio. –

+0

ma questo non significa che qualsiasi segno di dollaro che potrei avere nelle mie corde sarà scappato con una barra rovesciata? Esporto una tabella di grandi dimensioni e in realtà non esiste un particolare carattere che non appaia con certezza del 100%. L'escaping può essere disabilitato in qualche modo? –

2

La risposta da Simo Kivistö funziona se si è certi che il carattere $, o qualsiasi altra cosa la citazione speciale personaggio che hai scelto non compare nelle stringhe. Nel mio caso, ho dovuto esportare un tavolo molto grande e non c'era nessun carattere particolare che non compariva nelle stringhe.

Per ovviare a questo problema, ho convogliato l'output del comando COPY-sed ripristinare la doppia fuga di citazioni:

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

Il sed espressione Sono tubazioni per sostituisce semplicemente occorrenze di \\" con \".

+0

Ho avuto successo con una ricetta sed leggermente diversa: sostituire tutte le coppie backslash con una sola barra rovesciata: 'sed 's/\\\\/\\/g''. –

+0

Nelle versioni più recenti di Postgres (a partire dal 9.3 credo), puoi anche includere un filtro nell'istruzione COPY come 'COPY (SELECT row_to_json (t) da my_table as t) TO PROGRAM $$ sed 's/\\\\/\\/g '> my_table.json $$ ' –

Problemi correlati