Skip to content

JSONをPythonの辞書やオブジェクトに変換する方法、APIレスポンスの利用、ファイルの取り扱い、そして制限事項の確認について学びます。

Notifications You must be signed in to change notification settings

bright-jp/Parse-json-in-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 

Repository files navigation

PythonでJSONデータを解析する

Promo

このガイドでは、Pythonのjsonモジュールを使用してJSONデータを解析し、それをPythonの辞書に変換する方法、およびその逆の変換方法を解説します。

PythonにおけるJSONの概要

JavaScript Object Notation(JSON)は、APIを介してサーバーとWebアプリケーション間でデータを送受信する際に一般的に使用される、軽量なデータ交換フォーマットです。JSONデータはキーと値のペアで構成され、各キーは文字列であり、各値は文字列、数値、真偽値、null、配列、またはオブジェクトになり得ます。

以下はJSONの例です。

{
  "name": "Maria Smith",
  "age": 32,
  "isMarried": true,
  "hobbies": ["reading", "jogging"],
  "address": {
    "street": "123 Main St",
    "city": "San Francisco",
    "state": "CA",
    "zip": "12345"
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "555-555-1234"
    },
    {
      "type": "work",
      "number": "555-555-5678"
    }
  ],
  "notes": null
}

Pythonは、Python Standard Libraryの一部であるjsonモジュールを通じて、ネイティブにJSONをサポートしています。つまり、PythonでJSONを扱うために追加のライブラリをインストールする必要はありません。jsonは次のようにインポートできます。

import json

組み込みのPython jsonライブラリは、JSONを扱うための完全なAPIを提供します。特に重要な関数として、loadsloadの2つがあります。loads関数は文字列からJSONデータを解析するためのもので、load関数はJSONデータをbytesへ解析するためのものです。

これら2つのメソッドを通じて、jsonはJSONデータをdictionarieslistsなどの同等のPythonオブジェクトに変換でき、またその逆も可能です。さらにjsonモジュールは、特定のデータ型を扱うためのカスタムエンコーダーおよびデコーダーを作成できます。

PythonでJSONデータを解析する

JSON文字列をPython辞書に変換する

文字列に保存されたJSONデータがあり、それをPython辞書に変換したいとします。JSONデータは次のとおりです。

{
  "name": "iPear 23",
  "colors": ["black", "white", "red", "blue"],
  "price": 999.99,
  "inStock": true
}

そして、Pythonにおける文字列表現は次のとおりです。

smartphone_json = '{"name": "iPear 23", "colors": ["black", "white", "red", "blue"], "price": 999.99, "inStock": true}'

Note
長い複数行のJSON文字列を保存する場合は、Pythonのトリプルクォートの慣習の使用をご検討ください。

smartphoneに有効なPython文字列が入っていることは、次の行で確認できます。

print(type(smartphone))

出力は次のとおりです。

<class 'str'>

strは「string」を意味し、smartphone変数がテキストシーケンス型であることを示します。

smartphoneに含まれるJSON文字列を、json.loads()メソッドでPython辞書に解析するには次のようにします。

import json

# JSON string
smartphone_json = '{"name": "iPear 23", "colors": ["black", "white", "red", "blue"], "price": 999.99, "inStock": true}'
# from JSON string to Python dict
smartphone_dict = json.loads(smartphone_json)

# verify the type of the resulting variable
print(type(smartphone_dict)) # dict

このスニペットを実行すると、次の結果になります。

<class 'dict'>

これでsmartphone_dictには有効なPython辞書が含まれます。

次に、有効なJSON文字列をjson.loads()に渡して、JSON文字列をPython辞書に変換します。

これで、生成された辞書のフィールドには通常どおりアクセスできます。

product = smartphone_dict['name'] # smartphone
priced = smartphone['price'] # 999.99
colors = smartphone['colors'] # ['black', 'white', 'red', 'blue']

json.loads()関数は常に辞書を返すとは限りません。具体的には、戻り値のデータ型は入力文字列に依存します。たとえば、JSON文字列が単一の値(フラットな値)を含む場合、それは同等のPythonプリミティブ値に変換されます。

import json
 
json_string = '15.5'
float_var = json.loads(json_string)

print(type(float_var)) # <class 'float'>

同様に、配列リストを含むJSON文字列はPythonのリストになります。

import json
 
json_string = '[1, 2, 3]'
list_var = json.loads(json_string)
print(json_string) # <class 'list'>

以下の変換表は、JSONの値がjsonによってどのようにPythonデータへ変換されるかを説明しています。

| JSON Value | Python Data | | - | - | - | | string | str | | number (integer) | int | | number (real) | float | | true | True | | false | False | | null | None | | array | list | | object | dict |

JSON APIレスポンスをPython辞書に変換する

APIを呼び出し、そのJSONレスポンスをPython辞書に変換する必要があるとします。以下の例では、{JSON} Placeholderプロジェクトの次のAPIエンドポイントを呼び出して、ダミーのJSONデータを取得します。

https://jsonplaceholder.typicode.com/todos/1

このRESTFul APIは次のJSONレスポンスを返します。

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Standard LibraryのurllibモジュールでこのAPIを呼び出し、得られたJSONを次のようにPython辞書に変換できます。

import urllib.request
import json

url = "https://jsonplaceholder.typicode.com/todos/1"

with urllib.request.urlopen(url) as response:
     body_json = response.read()

body_dict = json.loads(body_json)
user_id = body_dict['userId'] # 1

urllib.request.urlopen()はAPI呼び出しを実行し、HTTPResponseオブジェクトを返します。続いて、そのread()メソッドを使用してレスポンスボディbody_jsonを取得します。これにはAPIレスポンスがJSON文字列として含まれています。最後に、先ほど説明したとおり、その文字列をjson.loads()でPython辞書に解析できます。

同様に、requests:を使って同じ結果を得ることもできます。

import requests
import json

url = "https://jsonplaceholder.typicode.com/todos/1"
response = requests.get(url)

body_dict = response.json()
user_id = body_dict['userId'] # 1

Note
.json()メソッドは、JSONデータを含むレスポンスオブジェクトを対応するPythonデータ構造へ自動的に変換します。

JSONファイルをPython辞書に読み込む

次のようなJSONデータがsmartphone.jsonファイルに保存されているとします。

{
  "name": "iPear 23",
  "colors": ["black", "white", "red", "blue"],
  "price": 999.99,
  "inStock": true,
  "dimensions": {
    "width": 2.82,
    "height": 5.78,
    "depth": 0.30
  },
  "features": [
    "5G",
    "HD display",
    "Dual camera"
  ]
}

目的はJSONファイルを読み込み、それをPython辞書にロードすることです。次のスニペットで実現できます。

import json

with open('smartphone.json') as file:
  smartphone_dict = json.load(file)

print(type(smartphone_dict)) # <class 'dict'>
features = smartphone_dict['features'] # ['5G', 'HD display', 'Dual camera']

組み込みのopen()ライブラリを使用すると、ファイルをロードして対応するfile objectを取得できます。続いてjson.read()メソッドが、JSONドキュメントを含むtext fileまたはbinary fileを、同等のPythonオブジェクトへデシリアライズします。この場合、smartphone.jsonはPython辞書になります。

JSONデータからカスタムPythonオブジェクトへ

次に、JSONデータをカスタムPythonクラスへ解析してみましょう。カスタムSmartphone Pythonクラスは次のとおりです。

class Smartphone:
    def __init__(self, name, colors, price, in_stock):
        self.name = name    
        self.colors = colors
        self.price = price
        self.in_stock = in_stock

ここでの目的は、次のJSON文字列をSmartphoneインスタンスに変換することです。

{
  "name": "iPear 23 Plus",
  "colors": ["black", "white", "gold"],
  "price": 1299.99,
  "inStock": false
}

このタスクを達成するために、カスタムデコーダーを作成します。そのためには、JSONDecoderクラスを拡張し、__init__メソッドでobject_hookパラメータを設定します。これには、カスタム解析ロジックを含むクラスメソッド名を割り当てます。その解析メソッド内では、json.read()が返す標準辞書に含まれる値を使ってSmartphoneオブジェクトをインスタンス化できます。

以下のようにカスタムSmartphoneDecoderを定義します。

import json
 
class SmartphoneDecoder(json.JSONDecoder):
    def __init__(self, object_hook=None, *args, **kwargs):
        # set the custom object_hook method
        super().__init__(object_hook=self.object_hook, *args, **kwargs)

    # class method containing the 
    # custom parsing logic
    def object_hook(self, json_dict):
        new_smartphone = Smartphone(
            json_dict.get('name'), 
            json_dict.get('colors'), 
            json_dict.get('price'),
            json_dict.get('inStock'),            
        )

        return new_smartphone

カスタムobject_hook()メソッド内で辞書の値を読むにはget()メソッドを使用します。これにより、辞書にキーが存在しない場合でもKeyErrorが発生しないようにできます。代わりにNoneが返されます。

次に、json.loads()clsパラメータにSmartphoneDecoderクラスを渡して、JSON文字列をSmartphoneオブジェクトに変換します。

import json

# class Smartphone:
# ...

# class SmartphoneDecoder(json.JSONDecoder): 
# ...

smartphone_json = '{"name": "iPear 23 Plus", "colors": ["black", "white", "gold"], "price": 1299.99, "inStock": false}'

smartphone = json.loads(smartphone_json, cls=SmartphoneDecoder)
print(type(smartphone)) # <class '__main__.Smartphone'>
name = smartphone.name # iPear 23 Plus

同様に、json.load()でもSmartphoneDecoderを使用できます。

smartphone = json.load(smartphone_json_file, cls=SmartphoneDecoder)

PythonデータをJSONに変換する

逆方向に、Pythonのデータ構造やプリミティブ型をJSONに変換することも可能です。これはjson.dump()およびjson.dumps()関数により可能で、以下の変換表に従います。

| Python Data | JSON Value | | - | - | - | | str | string | | int | number (integer) | | float | number (real) | | True | true | | False | false | | None | null | | list | array | | dict | object | | Null | None  |

json.dump()を使用すると、次の例のようにJSON文字列をファイルへ書き込めます。

import json

user_dict = {
    "name": "John",
    "surname": "Williams",
    "age": 48,
    "city": "New York"
}

# serializing the sample dictionary to a JSON file
with open("user.json", "w") as json_file:
    json.dump(user_dict, json_file)

このスニペットは、Pythonのuser_dict変数をuser.jsonファイルにシリアライズします。

同様に、json.dumps()はPython変数を同等のJSON文字列に変換します。

import json

user_dict = {
    "name": "John",
    "surname": "Williams",
    "age": 48,
    "city": "New York"
}

user_json_string = json.dumps(user_dict)

print(user_json_string)

このスニペットを実行すると、次の結果が得られます。

{"name": "John", "surname": "Williams", "age": 48, "city": "New York"}

Note
カスタムエンコーダーの指定方法については、公式ドキュメントに従ってください。

json標準モジュールの制限

JSONのデータ解析には、見過ごせない課題があります。

代表的な例は次の2つです。

  • Pythonのjsonモジュールは、無効、破損、または非標準のJSONの場合に不十分になることがあります。
  • 信頼できないソースからのJSONデータの解析は危険です。悪意のあるJSON文字列により、パーサーが壊れたり、大量のリソースを消費したりする可能性があります。

これらの制限は回避できますが、Web Scraper APIのようにJSON解析を容易にする商用ツールを使用するのが最適です。

結論

Pythonでjson標準モジュールを通じてJSONデータをネイティブに解析する場合、Webサイトによって課される制限を回避するために、信頼性の高いプロキシサーバーが必要になります。Bright Dataのデータおよびプロキシ製品のような、最先端でフル機能の商用ソリューションによるデータ解析をお試しください。

About

JSONをPythonの辞書やオブジェクトに変換する方法、APIレスポンスの利用、ファイルの取り扱い、そして制限事項の確認について学びます。

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published