質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

864閲覧

jsonファイルのKeyErrorを一括で例外処理する方法について

kouki_prog

総合スコア2

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

1グッド

1クリップ

投稿2022/05/16 04:05

編集2022/05/16 15:05

AmazonAPIから取得したjsonファイルの情報の抽出をしようとしています。

jsonファイルは、商品によって要素(商品サイズ等)がある場合とない場合が分かれています。

要素が無いときに、KeyErrorが発生したため、try-exceptで例外処理していますが、抽出する要素数が各商品20種類と多いためコードが長くなっています。

KeyErrorで検索して、「.get()で取得すれば要素が無いときはKeyErrorが出ない」と理解したのですが、.get()で要素を抽出しても、間の[0]で要素が見つからず、IndexErrorが発生してしまいます。
example:
json_a.get("a")[0].get("b").get("c")

IndexErrorを例外処理するかKeyErrorを例外処理するかの違いだけでした。

【質問】
要素があったりなかったりする場合、jsonからの要素の抽出は一つ一つ例外処理を書いていくしかないのでしょうか?

【変更点】
ソースコードとjsonを追記しました。

json例

json

1response_json = 2 { 3 "asin": "B0872MYW83", 4 "identifiers": [ 5 { 6 "marketplaceId": "A1VC38T7YXB528", 7 "identifiers": [ 8 { 9 "identifier": "4902777309934", 10 "identifierType": "EAN" 11 } 12 ] 13 } 14 ], 15  ・・・中略 16 "summaries": [ 17 { 18 "marketplaceId": "A1VC38T7YXB528", 19 "brandName": "NEXT BODY(\u30cd\u30af\u30b9\u30c8 \u30dc\u30c7\u30a3)", 20 "browseNode": "3457072051", 21 "itemName": "[Amazon\u9650\u5b9a\u30d6\u30e9\u30f3\u30c9] \u660e\u6cbb \u30b6\u30d0\u30b9(SAVAS) \u30db\u30a8\u30a4\u30d7\u30ed\u30c6\u30a4\u30f3 \u30b3\u30b3\u30a2\u5473\u301051\u98df\u5206\u3011 1,071g NEXT BODY", 22 "manufacturer": "\u660e\u6cbb", 23 "modelNumber": "2630993", 24 "sizeName": "1.071\u30ad\u30ed\u30b0\u30e9\u30e0 (x 1)" 25 } 26 ], 27 "variations": [] 28}

プログラム

Python

1json_tmp = json.loads(response_json) 2 3 try: 4 jan = json_tmp.get('identifiers')[0].get('identifiers')[0].get('identifier') 5 except (IndexError,AttributeError): 6 jan = '' 7 try: 8 major_rank = json_tmp.get('ranks')[0].get('ranks')[0].get('rank') 9 except (IndexError,AttributeError): 10 major_rank = '' 11 try: 12 minor_rank = json_tmp.get('ranks')[0].get('ranks')[1].get('rank') 13 except (IndexError,AttributeError): 14 minor_rank = '' 15 try: 16 junre = json_tmp.get('ranks')[0].get('ranks')[0].get('title') 17 except (IndexError,AttributeError): 18 junre = '' 19 try: 20 item_name = json_tmp.get('summaries')[0].get('itemName') 21 except (IndexError,AttributeError): 22 item_name = '' 23 try: 24 brand_name = json_tmp.get('summaries')[0].get('brandName') 25 except (IndexError,AttributeError): 26 brand_name = '' 27 try: 28 manufacturer = json_tmp.get('summaries')[0].get('manufacturer') 29 except (IndexError,AttributeError): 30 manufacturer = '' 31 try: 32 model_number = json_tmp.get('summaries')[0].get('modelNumber') 33 except (IndexError,AttributeError): 34 model_number = '' 35 try: 36 valiations = json_tmp.get('variations') 37 except (IndexError,AttributeError): 38 valiations = ''
yuki23👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2022/05/16 08:49 編集

回答ではないですが、言語を変えると、このあたりは楽に書けます。近い言語だとRuby。
yuki23

2022/05/16 11:51

問題が何なのかよくわからないので、ソースコードを提示していただけますか?
kouki_prog

2022/05/16 15:06 編集

otn様 アドバイスいただきありがとうございます。 やっぱり、言語により得手不得手があるんですね。 知識不足の中、作成途中のアプリがPythonなので、手持ちの札でなんとかしようと四苦八苦しております。 yuki23様 ご確認いただきありがとうございます。 ソースコードを本文に追記いたしました。 よろしくおねがいします。
guest

回答2

0

普通に考えると、そういう関数を定義するのでしょうか。
例として書くと、

Python

1def dig(data, *xx): 2 for x in xx: 3 if isinstance (data,list): 4 if x>=0 and x<len(data): 5 data = data[x] 6 else: 7 return "" 8 elif isinstance (data,dict): 9 data = data.get(x) 10 else: 11 return "" 12 return data 13 14jan = dig(json_tmp, 'identifiers', 0, 'identifiers', 0, 'identifier') 15major_rank = dig(json_tmp, 'ranks', 0, 'ranks', 0, 'rank') 16minor_rank = dig(json_tmp, 'ranks', 0, 'ranks', 1, 'rank') 17junre = dig(json_tmp, 'ranks', 0, 'ranks', 0, 'title') 18item_name = dig(json_tmp, 'summaries', 0, 'itemName') 19brand_name = dig(json_tmp, 'summaries', 0, 'brandName') 20manufacturer = dig(json_tmp, 'summaries', 0, 'manufacturer') 21model_number = dig(json_tmp, 'summaries', 0, 'modelNumber') 22valiations = dig(json_tmp, 'variations')

Pythonのライブラリはあまり知らないので、同様の物が標準ですでにあるかもしれません。

投稿2022/05/16 15:55

otn

総合スコア84538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kouki_prog

2022/05/17 11:17

otn様 ありがとうございました! 関数定義で回避する考えがありませんでした。 instance関数も初見だったので勉強になりました。
otn

2022/05/17 12:10 編集

Rubyだと、 json_tmp.dig('identifiers', 0, 'identifiers', 0, 'identifier') という dig メソッドが、Pythonでいうと list や dict に相当するクラス等に提供されています。途中で該当要素が無ければ nil (PythonでいうNone)を返す。
guest

0

ベストアンサー

他の言語に比べるとあまり書きやすくはありませんが、get の引数に無効値を与えれば例外を使わないことはできます。

例:

py

1major_rank = json_tmp.get('ranks', [{}])[0].get('ranks', [{}])[0].get('rank', '')

投稿2022/05/16 15:38

yuki23

総合スコア1448

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kouki_prog

2022/05/17 11:21

yuki23様 ありがとうございました! まさに求めていた例外を発生させずに書く方法でした。 getのデフォルト値に入れると回避できるんですね。第二引数があることすら知らなかったので、勉強不足でした。 困ったときにはドキュメントを見るようにします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問