はじめに
コーナーケースすぎるけど下記のようなケースです。
- Python プログラムから直接PostgreSQLに接続するのでなく、Postgres のJSON配列の値を、ほかのデータベースのテキスト型の列か、ファイルなどに、文字列、テキストとして保存する
- Pythonからはその保存されたデータを読み込んで、PythonのJSONとして扱いたい
PostgreSQL
Postgres あるテーブルからデータをJSON 型で抽出するときの小ネタ - はじまる で使った Animals テーブルをまた利用します。
SELECT * FROM Animals;
id | name | age | kind |
---|---|---|---|
1 | Mickey | 5 | Mouse |
2 | Snoopy | 3 | Dog |
3 | Kitty | 3 | Cat |
これを array_agg
などでJSONを格納した配列に変換します。
WITH AnimalJSON AS ( SELECT id, ( select row_to_json(_) from (select name, age, kind) as _ ) as attributes FROM Animals ) SELECT array_agg(attributes) FROM AnimalJSON
array_agg |
---|
{"{\"name\":\"Mickey\",\"age\":5,\"kind\":\"Mouse\"}","{\"name\":\"Snoopy\",\"age\":3,\"kind\":\"Dog\"}","{\"name\":\"Kitty\",\"age\":3,\"kind\":\"Cat\"}"} |
この値が適当なデータストアに保存されており、それをPythonで扱いたい時の話です。
Python
上記の array_agg の結果が、文字列として格納されている状態です。Python から読み取り、 str
型の変数 string
に入力されているとします。
print(string) >>>{"{\"name\":\"Mickey\",\"age\":5,\"kind\":\"Mouse\"}","{\"name\":\"Snoopy\",\"age\":3,\"kind\":\"Dog\"}","{\"name\":\"Kitty\",\"age\":3,\"kind\":\"Cat\"}"} print(repr(string)) >>>'{"{\\"name\\":\\"Mickey\\",\\"age\\":5,\\"kind\\":\\"Mouse\\"}","{\\"name\\":\\"Snoopy\\",\\"age\\":3,\\"kind\\":\\"Dog\\"}","{\\"name\\":\\"Kitty\\",\\"age\\":3,\\"kind\\":\\"Cat\\"}"}'
この string
をどうPython での JSONに変えていくかですが、結論としては下記のようなアプローチがいいかと感じました。
- str から set に変換する
- set から JSON に変換する
まず eval()
を使うことで、str
から set
に型変換します。
>>> string = repr(string) >>> type(string) <class 'str'> >>> eval(string) {'{"name":"Kitty","age":3,"kind":"Cat"}', '{"name":"Snoopy","age":3,"kind":"Dog"}', '{"name":"Mickey","age":5,"kind":"Mouse"}'} >>> type(eval(string)) <class 'set'>
ここで、配列の要素はまだ文字列になっています。これらの文字列を json.loads()
でJSONとしてパースします。
>>> new_list = [] >>> if type(eval(string)) == set: ... for i in eval(string): ... item = json.loads(i) ... new_list.append(item) ... >>> new_list [{'name': 'Kitty', 'age': 3, 'kind': 'Cat'}, {'name': 'Snoopy', 'age': 3, 'kind': 'Dog'}, {'name': 'Mickey', 'age': 5, 'kind': 'Mouse'}]