Запись фрейма данных в CSV, где списки преобразуются в массивы JSON

Как будет выводиться список строк в виде массива JSON при записи кадра данных в CSV?

Например ['foo', 'bar'] должно быть ["foo", "bar"]


Фон

Я копирую данные из базы данных PostgreSQL в AWS RDS в AWS Redshift. В качестве промежуточного шага данные должны быть загружены в AWS S3 в файлах CSV.

Но Redshift не поддерживает массивы как тип данных. Массивы необходимо преобразовать в varchar, представляющий массив JSON.

Например, столбец типа character varying(255)[] на RDS потребуется столбец типа character varying(MAX) на Redshift и использовать функции JSON для взаимодействия с данными.

Если данные не загружаются в Redshift как массив JSON, они не будут действительными.

         json_arrays          | is_valid_json_array
------------------------------+---------------------
 []                           | T
 ["a","b"]                    | T
 ["a",["b",1,["c",2,3,null]]] | T
 {"a":1}                      | F
 a                            | F
 {foo, bar}                   | F
 {"one", "two"}               | F
 [x,y,z]                      | F
 [1,2,]                       | F
 ['x','y','z']                | F

Сложность в том, что Python представляет строки внутри одинарных кавычек, поэтому при записи списка строк в CSV этот список будет использовать одинарные кавычки, которые не являются допустимым массивом JSON.


Неудачным подходом было преобразование массива при чтении CSV.

def convert_pg_array_to_json_array(a):
    """
    Converts a PG array such as '{foo,bar}' to '["foo", "bar"]'
    """
    return json.dumps(a[1:-1].split(','))

# The arrays to convert are in column 20
df = pandas.read_csv(path, converters={20: convert_pg_array_to_json_array})

# Array gets output as "[""foo"", ""bar""]" which is not a valid JSON array
# Desired output is ["foo", "bar"]
df.to_csv(path)

1 ответ

Объедините подход в вопросе с этими изменениями при написании CSV:
Настроить escape-символ (как правило, обратную косую черту \) и отключить двойные кавычки.

df.to_csv(path, escapechar="\\", doublequote=False)

Строка в CSV будет выглядеть [\"foo\", \"bar\"] который является допустимым JSON, если вы загружаете данные с экранированием от обратной косой черты. Для красного смещения COPY FROM вам нужно будет добавить ESCAPE вариант к запросу.

Другие вопросы по тегам