【Python】JSONフォーマットの使い方(jsonモジュール)

Python データソースと書式 モジュール

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つの構造を基にしています。

  • 名前/値のペアの集まり。様々な言語で、これはオブジェクト、レコード、構造体、ディクショナリ、ハッシュテーブル、キーのあるリスト、連想配列として実現されています。
  • 値の順序付きリスト。ほとんどの言語で、これは配列として実現されています。

引用元:https://www.json.org/json-ja.html

もう少し具体的に書くと、、、

  • 配列:
  • 値を(,)(カンマ)で区切って、[](角かっこ)でくくる。

    ["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_asciitrueとなっているためで、日本語を日本語として表記するには、この引数を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をサポートしていることが多いので是非使いこなしたいです。

参考書籍

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!

シェアする
ひびきをフォローする
Hbk project

コメント

  1. […] PythonオブジェクトをJsonに変換したい場合はこの記事 […]