Экспортировать таблицу Postgres как json

35

Есть ли способ экспортировать данные таблицы postgres как json в файл? Мне нужно, чтобы вывод был построчно, например:

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

РЕДАКТИРОВАТЬ: postgres версия: 9.3.4

AliBZ
источник

Ответы:

48

Попробуйте здесь для основного введения в PostgreSQLи JSON.

Кроме того, документация PostgreSQL довольно хорошая, так что попробуйте здесь . Проверьте pretty_boolвариант.

Ваш первоначальный вопрос был «Есть ли способ экспортировать данные таблицы postgres как JSON». Вы хотели это в этом формате

{'id':1,'name':'David'}
{'id':2,'name':'James'}
...

У меня не было запущенного экземпляра, PostgreSQLпоэтому я скачал, скомпилировал и установил 9.4.

Чтобы ответить на это, я сначала CREATEотредактировал таблицу (Фред)

CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));

INSERT INTO fred VALUES (2,    43, 'asfasfasfd'      );
INSERT INTO fred VALUES (3,   435, 'ererere'         );
INSERT INTO fred VALUES (6, 43343, 'eresdfssfsfasfae');

Затем, чтобы проверить:

test=# select * from fred;

 mary | jimmy |      paulie      
------+-------+------------------
    2 |    43 | asfasfasfd
    3 |   435 | ererere
    6 | 43343 | eresdfssfsfasfae

Тогда я выпустил эту команду

test=# COPY (SELECT ROW_TO_JSON(t) 
test(# FROM (SELECT * FROM fred) t) 
test-# TO '/paulstuff/sware/db/postgres/inst/myfile';
COPY 3
test=# 

Затем я вышел из psql и перечислил файл myfile.

test=# \q
[pol@polhost inst]$ more myfile 
{"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
{"mary":3,"jimmy":435,"paulie":"ererere"}
{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
[pol@polhost inst]$

(вы можете поэкспериментировать с выводом из

COPY (SELECT ROW_TO_JSON(t, TRUE)  -- <-- Note addition of "TRUE" here!

в свободное время).

@ Offby1 указал, что вывод (хотя и соответствует вопросу ОП) не верен JSON. @EvanCarroll указал, что \oэто также способ вывода в файл, поэтому я объединил решения этих двух проблем в этом утверждении (с помощью отсюда ):

test=# \o out.json
test=# SELECT array_to_json(array_agg(fred), FALSE) AS ok_json FROM fred;
                                     -- <-- "TRUE" here will produce plus
                                        ("+) signs in the output. "FALSE"
                                        is the default anyway.
test=# \o

дает:

[pol@polhost inst]$ more out.json 
                                                                   ok_json                                                                    
----------------------------------------------------------------------------------------------------------------------------------------------
 [{"mary":2,"jimmy":43,"paulie":"asfasfasfd"},{"mary":3,"jimmy":435,"paulie":"ererere"},{"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}]
(1 row)
[pol@polhost inst]$ 

Наконец , есть \проблема с обратным слешем ( ), на которую ссылается @AdamGent в своем посте. Это было немного сложно, но это возможно , не прибегая к обработке после запроса. Вуаля:

INSERT INTO fred VALUES (35, 5, 'wrew\sdfsd');
INSERT INTO fred VALUES (3, 44545, '\sdfs\\\sfs\\gf');

И используя REGEXP_REPLACE, таким образом (обратите внимание на cast :: TEXT) удаляются лишние черные черты.

test=# \o slash.json
test=# SELECT REGEXP_REPLACE(ROW_TO_JSON(t)::TEXT, '\\\\', '\\', 'g') 
test=# FROM (SELECT * FROM fred) AS t;  -- I found that using a CTE was helpful for legibility
test=# \o
test=# \q

дает:

[pol@polhost inst]$ more slash.json 
                    regexp_replace                    
------------------------------------------------------
 {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}
 {"mary":3,"jimmy":435,"paulie":"ererere"}
 {"mary":6,"jimmy":43343,"paulie":"eresdfssfsfasfae"}
 {"mary":35,"jimmy":5,"paulie":"wrew\sdfsd"}
 {"mary":3,"jimmy":44545,"paulie":"\sdfs\\\sfs\\gf"}
(5 rows)
[pol@polhost inst]$ 

(ps Что касается комментария @ Zoltán - это может быть версия версии - невозможно воспроизвести!).

Verace
источник
2
Кажется, именно этого и хотел оригинальный плакат. Тем не менее, обратите внимание, что хотя каждая строка является надлежащим JSON, коллекция строк - нет, поскольку в ней отсутствуют запятые, разделяющие строки, и квадратные скобки, окружающие их.
offby1
3
Это НЕ будет работать , если у вас есть backslashв ваших колонках !!!! Внимательно прочитайте документ COPY, так как он выполняет специальные функции для backslashперсонажей (например, добавляет еще одну обратную косую черту).
Адам Гент
ПРОЧИТАЙТЕ ответ @AdamGent ниже, чтобы решить проблему обратной косой черты
FacePalm
1
Итак ... год 2017 и НЕТ СПОСОБА ЭКСПОРТИРОВАТЬ JSON с помощью команды COPY PostgreSQL ?? Есть опция CSV, опция TXT ... Почему не опция JSON?
Питер Краусс
1
Спасибо @ Vérace. И извините, теперь я протестировал COPY со сложным JSONb, и обработанный JSON был в порядке, "правильный JSON"!
Питер Краусс
13

Если вы используете, psqlто нет никаких оснований для использования \COPYвообще.

\t
\a
\o file.json
SELECT row_to_json(r) FROM my_table AS r;

Это тот же метод, который мы используем для извлечения png / jpgs / tifs из базы данных с PostGIS для быстрых тестов, а также для создания файлов сценариев с расширениями PostgreSQL.

Эван Кэрролл
источник
Большой! Как обычно, команда COPY "не разрешать относительный путь" , psql-native-команды - это самый простой способ скопировать в относительный путь ! PS: существует «терминальный способ» использования реальной команды COPY с относительным путем, см. Здесь . psql -h remotehost -d remote_mydb -U myuser -c "COPY (SELECT '{\"x\":1,\"y\":[\"a\",2]}'::json AS r) TO STDOUT" > ./relative_path/file.csv
Питер Краусс
6

Для меня ответ @Vérace не содержал имена столбцов, а присваивал им имена по умолчанию ( f1, f2и т. Д.). Я использую PostgreSQL 9.1 с расширением JSON .

Если вы хотите экспортировать всю таблицу, подзапрос не требуется. Кроме того, это будет поддерживать имена столбцов. Я использовал следующий запрос:

COPY (SELECT row_to_json(t) FROM fred as t) to '/home/pol/Downloads/software/postgres/inst/myfile';
Золтан
источник
Он сохранил имена столбцов! CREATE TABLE fred (mary INT, jimmy INT, paulie VARCHAR(20));и результат: {"mary":2,"jimmy":43,"paulie":"asfasfasfd"}- имена полей: mary, jimmy, paulie ... и NOT ( f1, f2и т. д.) ...
Vérace
5

Я добавлю специальное предостережение к ответу Веры . Вам нужно сделать постобработку на выводимый файл JSON , если у вас есть текстовые столбцы с обратной косой чертой:\ .

В противном случае вы получите дубликат ( \-> \\) в лучшем случае и совершенно неверный JSON в худшем случае, т.е.

Это:

{ "f1" : "crap\""}.

становится

{ "f1" : "crap\\""}.

Который выглядит хорошо, но совершенно неверный JSON.

Вы можете заменить \\на \sed:

sed -i -e 's/\\\\/\\/g' PG_OUT_JSON_FILE.json

От Postgres COPY, где они об этом упоминают:

В настоящее время COPY TO никогда не будет генерировать восьмеричную или восьмеричную последовательность с обратной косой чертой, но она использует другие последовательности, перечисленные выше для этих управляющих символов. Любой другой символ с обратной косой чертой, не упомянутый в приведенной выше таблице, будет представлен как сам. Однако остерегайтесь ненужного добавления обратной косой черты, поскольку это может случайно привести к строке, совпадающей с маркером конца данных (.) Или пустой строкой (по умолчанию \ N). Эти строки будут распознаны до выполнения любой другой обратной косой черты.

Настоятельно рекомендуется, чтобы приложения, генерирующие данные COPY, преобразовывали символы новой строки и возврат каретки в последовательности \ n и \ r соответственно. В настоящее время можно представить возврат каретки данных с помощью обратной косой черты и возврата каретки, а также перевод новой строки данных с помощью обратной косой черты и новой строки. Тем не менее, эти представления могут быть не приняты в будущих выпусках. Они также очень уязвимы для повреждения, если файл COPY передается на разные машины (например, из Unix в Windows или наоборот).

COPY TO завершит каждую строку символом новой строки в стиле Unix ("\ n"). Серверы, работающие в Microsoft Windows, вместо этого выводят символ возврата каретки / новой строки ("\ r \ n"), но только для COPY в файл сервера; для согласованности между платформами, COPY TO STDOUT всегда отправляет «\ n» независимо от серверной платформы. COPY FROM может обрабатывать строки, заканчивающиеся символами новой строки, возврата каретки или возврата каретки / перевода строки. Чтобы уменьшить риск ошибки из-за непоследовательных косых черт или возвратов каретки, которые подразумевались как данные, COPY FROM будет выдавать жалобу, если окончания строк во входных данных не совпадают.

Адам Гент
источник
Я имел дело с этим в ответе - надеюсь, вы найдете его удовлетворительным. Если нет, дайте мне знать.
Вера
1

Для общего (MySQL, Postgres, SQLite ..) и бесплатного решения, для которого вам не нужно устанавливать какое-либо программное обеспечение (кроме Docker), см. Https://github.com/function61/sql2json

Полное раскрытие: я написал это программное обеспечение.

joonas.fi
источник
0

Это единственный метод, который выводит допустимый JSON (массив объектов).

\t
\a
\o data.json
select json_agg(t) FROM (SELECT * from table) t;

( источник )

Гунар Гесснер
источник