yuki_2020
@yuki_2020

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

apiからとってきたJSONデータ保存するいい方法ありませんか

はじめに

apiを使ってwebサイトからJSON形式でデータを収集しています。
今まではデータを処理して、必要な部分だけ集めていました。
しかし他にもデータを活用しようと思い、いっそのことapiのリスポンスを全て保存しようと思いました。

文字列のまま保存してもいいのですが、いちいちPythonでパースして辞書形式にして解析するのは大変です。

解決したいこと

一般論でも、pythonでも構いませんが、apiのJSON構造のレスポンスを保存する方法を教えて欲しいです。
できればcsvのように中身を確認しやすいものがいいですが、一番はapiのレスポンスに可逆的に戻すことができることです。

自分で試したこと

JSONをパースしてpandasのデータフレーム形式にしてcsvで保存していますが、辞書の中の辞書がうまく変換できないので、変えたいと思っています。

0

文字列のまま保存してもいいのですが、いちいちPythonでパースして辞書形式にして解析するのは大変です。

ここがよく分かりません。
JSONと辞書の区別はついていらっしゃるようですが、JSONとはある形式の文字列です。
ですので、JSONを保存するとは、文字列を保存することに他なりません。

あるいはレスポンスを表す何かしらのPythonオブジェクト(辞書、あるいはrequests.Responseかもしれない)をシリアライズしたいということでしょうか。
「JSON」あるいは「APIのレスポンス」がPython上で何という型として表現されているのかを明示的にしてくださると、より的を射た回答ができると思います。

以下は、APIの応答が辞書として表されているとします。

辞書をJSONとしてテキストファイルに保存する場合:

import json

# 読み込み
with open('filename') as f:
    d = json.load(f)

# 書き込み
with open('filename', 'w') as f:
    json.dump(d, f)

辞書をpickleモジュールでシリアライズする場合:

import pickle

# 読み込み
with open('filename', 'rb') as f:
    d = pickle.load(f)

# 書き込み
with open('filename', 'wb') as f:
    pickle.dump(d, f)

後者は辞書以外のオブジェクトにもある程度適用できます。

1Like

@eudika さん
コメントありがとうございます。

質問があいまいだったので補足します。

今回、apiからのリスポンスはもちろんJSON形式の文字列で、以下のようにjson.loads()を使用することで辞書形式のようなJsonDictのオブジェクトに変換して使用しています。

サーバー →api → JSON形式のstr →json.loads()→ JsonDict

JsonDictになった状態でのデータの一部は以下です。

{
  'id': 9567,
  'title': '一月まとめ',
  'type': 'illust',
  'caption': 'テスト',
  'restrict': 0,
  'user': {
    'id': 24389,
    'name': 'メル',
    'account': 'user',
    'tags': [{
      'name': 'マイキャラ',
      'translated_name': 'my character'
    }, {
      'name': 'ポケモン',
      'translated_name': 'Pokémon'
    }, {
      'name': 'ポケットモンスター',
      'translated_name': 'pocket monsters'
    }, {
      'name': 'pokemon',
      'translated_name': None
    }, {
      'name': 'ヒスイ地方',
      'translated_name': None
    }]
  }
}

もちろんstrオブジェクトの状態でjson.dump()を使用して保存することもできますが、そうするとただの文字列なのでメモ帳などで開いたときに可読性が悪いです。

また、pickleに関しても、オブジェクトと保存することは魅力的ですが、pythonで読み込まないと中身が見れません。

以下の画像のようなcsv形式のデータセットのように、パッと見てわかりやすく、かつ可逆的にもとのオブジェクトに戻せる保存方法はないでしょうか。

image.png

データ化学工学研究室(金子研究室)@明治大学 理工学部 応用化学科
データセット作成のときに注意する6つのこと
https://datachemeng.com/post-3886/
より引用

0Like

意図されるところは理解しました。

JsonDictとはご自身でデコーダーを介して得た型でしょうか。
json.load[s]の返値はデフォルトでdictだと理解しています。)
何にせよ、レスポンス本文を表す辞書のようなオブジェクトが手元にあって、
それを可読性の高い形式で永続化したいということですね。

そうすると、何を持って可読性とするかですが、
もしデフォルトのコンパクトな出力が見づらいということならば、
json.dump[s]にいくつかキーワード引数を渡すことで人の目に堪える表示になります。

json.dump(d, f, sort_keys=True, indent=4)

また、エディタにプラグインを導入したり、
あるいは専用のビューワーを用いるなど、JSONを閲覧する環境も工夫しましょう。
そういったビューワーにはシンタクスハイライトはもちろんとして、
中には、キーの開閉やクエリ機能を備えているものもあります。

そうではなく、表形式へのこだわりがあるのであれば、これは少し難しい話になります。
ご指摘の通り、二次元の表ではJSONの入れ子構造をそのまま表現することができないためです1
(いわゆるO-Rミスマッチに通じる話です。)

私ならどうするかというと、ひとまずデータはJSONで保存しておいて、
目的に適したビュー(見た目)を、Jupyter Notebook上でPandasなどで作ります。
データが変更されたら、再実行すれば良いですし、その場で加工もできます。

いずれにしても、永続化に適した形式それを閲覧する環境を分けて考えるのがポイントだと思います。

  1. ただ、方法がないという訳ではなくて、たとえばこのVSCodeプラグインのように、
    JSONをテーブル形式で表示してくれるビューワーもあるようです。
    (調べて見つけただけなので、使用感は知りません。
    おそらくもっと使い勝手の良いものもあるでしょう。)

2Like

@eudika さん

永続化に適した形式とそれを閲覧する環境を分けて考えるのがポイントだと思います。

確かにその通りだと思います。
この二つを同時にやろうとしてうまくいっていないことがわかりました。

JSONをテーブル形式で表示することについて、自分でプログラム作らなきゃなあと思っていたのですが、自動で見やすいテーブルに変換してくれるサービスを発見しました。
紹介していただいたVSCodeのプラグインは使用した結果いまいちでしたが、とても参考になりました。ありがとうございます。
いちいちコピペしなければいけない、セキュリティ的にまずいということを除けばよさそうです。

image.png

image.png

image.png

今後は、Json形式で保存し、中を見たいときは上記のサイトを使用していきたいと思います。

ただ、できればローカルでJsonファイルを上記のようにクリックで深い階層のデータを見ていきたいので、そのようなことができるtable形式に変換してくれるライブラリなどありましたら、教えてほしいです。

1Like

Your answer might help someone💌