JSONは Web APIなどのデータ交換形式としても広く使われているデータ形式です。Python標準の組込みモジュールであるjsonを使ってJSONデータを扱うことができます。本記事では、
- Web APIからのレスポンスを文字列として取得し、それをPythonオブジェクトへ変換
- PythonオブジェクトからJSON形式でファイル保存
- 日本語(非ASCII文字)のUnicodeエスケープ
等について整理しました。
また最後に、実際のWeb APIを使った具体例も記載しました。
JSONについて
JSONとは?
- “JavaScript Object Notation”の略。javascriptの仕様の一部として作られた軽量なデータ形式
- JavaScript専用のデータ形式ではなく、様々なソフトウェア、プログラミング言語間におけるデータ交換に使えるよう設計されている
- Web APIなどのデータ交換形式としても広く使われている
データフォーマット
JSON公式?から引用します。
JSONは2つの構造を基にしています。
- 名前/値のペアの集まり。様々な言語で、これはオブジェクト、レコード、構造体、ディクショナリ、ハッシュテーブル、キーのあるリスト、連想配列として実現されています。
- 値の順序付きリスト。ほとんどの言語で、これは配列として実現されています。
もう少し具体的に書くと、、、
- 配列:
値を(,)(カンマ)で区切って、[](角かっこ)でくくる。
["aaa", "bbb", "ccc"]
キーと値のペアを”:”(コロン)でペアにして、これらのペアを’,'(コンマ)で区切って全体を{}でくくる。
{"Item": "Book", "price": 1200}
ここで、キーは文字列に限ることに注意。つまり、
{item: "Book", price: 1200}
という表記は、キーが変数に見えてしまうのでJSONとしては不正となります。
JSONでは文字列はダブルクォーテーション(“)で囲うこと。シングルクォーテーション(‘)だと以下のようなエラーになります。
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 3 (char 2)
JSONモジュールの使いかた
PythonでJSONデータを扱うには、jsonモジュールが便利です。
但し、JSONはPythonでサポートしている全てのデータ型を使える訳ではありません。使えるデータ型は以下に限定されることに注意です。
- 文字列
- 整数
- 浮動小数点
- ブール値
- リスト
- 辞書
- None
文字列をPythonオブジェクトへ変換
(JSONドキュメントを含んだ)文字列をPythonオブジェクトへ変換するには、loads()を使います。
例を以下に示します。
# JSON形式を含んだ文字列
>>> j = '[{"name": "Taro", "age": 14, "check": true}, {"name": "Jiro", "age": 23, "check": false}, {"name": "Tom", "age": 16, "check": false}]'
# jsonモジュールをimport
>>> import json
# 文字列をPythonオブジェクトへ変換
>>> json_data = json.loads(j)
# Pythonオブジェクト(辞書とリストの組み合わせ)
>>> json_data
[{'name': 'Taro', 'age': 14, 'check': True}, {'name': 'Jiro', 'age': 23, 'check': False}, {'name': 'Tom', 'age': 16, 'check': False}]
辞書とリストの組み合わせなので、Pythonコードの中で任意のデータを取得することが出来ます。
PythonオブジェクトをJSON形式のstrオブジェクトに変換
Pythonオブジェクト(例えば辞書とリストの組み合わせ)を、JSON形式のstrオブジェクトに変換するには、dumps()メソッドを使います。
使い方の例を以下に示します。
# 変換するデータ(リストと辞書の組み合わせ)
>>> data_python = [{'name': 'Taro', 'age': 14, 'check': True}, {'name': 'Jiro', 'age': 23, 'check': False}, {'name': 'Tom', 'age': 16, 'check': False}]
# jsonモジュールをimport
>>> import json
# dumps関数でJSONデータに変換
>>> data_json = json.dumps(data_python)
# JSONデータ
>>> data_json
'[{"name": "Taro", "age": 14, "check": true}, {"name": "Jiro", "age": 23, "check": false}, {"name": "Tom", "age": 16, "check": false}]'
jsonデータを見やすく整形する
dumps関数にindentパラメータを設定すると、print文で表示した時に見やすくなります。
>>> data_json = json.dumps(data_python, indent=4)
>>> print(data_json)
[
{
"name": "Taro",
"age": 14,
"check": true
},
{
"name": "Jiro",
"age": 23,
"check": false
},
{
"name": "Tom",
"age": 16,
"check": false
}
]
日本語文字が含まれている場合
dumps()では、デフォルトでは日本語のような非ASCII文字はUnicodeエスケープされます。
つまり、例えば日本語文字のりんごは\u308a\u3093\u3054といった表記で出力されます。
具体例で見てみます。
# 日本語が含まれたPythonオブジェクト
>>> data_python = [{'name': 'たろー', 'age': 14, 'check': True}, {'name': '次郎', 'age': 23, 'check': False}, {'name': 'Tom', 'age': 16, 'check': False}]
# dumps()でJSON形式に変換
>>> data_json = json.dumps(data_python, indent=4)
# 日本語の箇所がUnicodeエスケープされている(★部)
>>> print(data_json)
[
{
"name": "\u305f\u308d\u30fc", (★)
"age": 14,
"check": true
},
{
"name": "\u6b21\u90ce", (★)
"age": 23,
"check": false
},
{
"name": "Tom",
"age": 16,
"check": false
}
]
これはdumps()の引数ensure_asciiがtrueとなっているためで、日本語を日本語として表記するには、この引数をFalseにしてやります。
# ensure_ascii = Falseに設定
>>> data_json = json.dumps(data_python, indent=4, ensure_ascii=False)
>>> print(data_json)
[
{
"name": "たろー",
"age": 14,
"check": true
},
{
"name": "次郎",
"age": 23,
"check": false
},
{
"name": "Tom",
"age": 16,
"check": false
}
]
PythonオブジェクトをJSON形式でファイルへ保存する
dump()を使います。使い方は下記です。第3引数以降は細かいので割愛しています。
json.dump(obj, fp)
この関数は、PythonオブジェクトobjをJSON形式のfile-likeオブジェクトfpに格納します。
具体例を以下に示します。
>>> import json
>>> data_python = [{'name': 'たろー', 'age': 14, 'check': True}, {'name': '次郎', 'age': 23, 'check': False}, {'name': 'Tom', 'age': 16, 'check': False}]
>>> with open('sample.json', 'w') as fp:
... json.dump(data_python, fp, indent=4, ensure_ascii=False)
出力結果を確認します。前項で述べたindentやensure_asciiの設定も反映されていますね。
~$ cat sample.json
[
{
"name": "たろー",
"age": 14,
"check": true
},
{
"name": "次郎",
"age": 23,
"check": false
},
{
"name": "Tom",
"age": 16,
"check": false
}
]
実際にWeb APIにアクセスしてみる
例として、各種気象データの無料APIを提供するオンラインサービスのOpenWeather で現在の天気情報を取得してみます。
※使用するにはアカウント登録が必要ですが、お試しで使うには無料プランでも十分だと思います。
以下は東京都の現在の天気を取得するコード例です。
API Keyは別ファイル(config.py)から呼び出すようにしています。
import json
import requests
import config
# API keyはconfigy.pyから読み出す
API_KEY = config.API_KEY
# 東京のcity ID(http://bulk.openweathermap.org/sample/city.list.json.gz)
city_id = '1850147'
# API endpoint
url = 'https://api.openweathermap.org/data/2.5/weather'
# 言語は日本語、温度の単位は℃に設定
params = {"id": city_id, "appid" : API_KEY, 'lang': 'ja', 'units':'metric'}
res = requests.get(url, params=params)
# JSONフォーマットをPythonオブジェクト(辞書型)に変換
data = json.loads(res.text)
# 辞書データから所望の値を取り出す
location = data['name']
weather = data['weather'][0]['main']
tempreture = data['main']['temp']
humidity = data['main']['humidity']
print(f'現在、{location}の天気は{weather}、気温は{tempreture}℃、湿度は{humidity}%です。')
実行結果は以下です。
$ python web_api_openweather.py
現在、東京都の天気はClouds、気温は15.69℃、湿度は82%です。
確認した環境
- OS:Ubuntu20.04LTS
- Python 3.9.0
まとめ
Pythonの標準ライブラリのjsonモジュールを使ってJSON形式データを扱う方法についてまとめました。
Web APIのレスポンスフォーマットとしてjsonをサポートしていることが多いので是非使いこなしたいです。
コメント
[…] PythonオブジェクトをJsonに変換したい場合はこの記事 […]