Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのjsonモジュール徹底解説:JSONエンコーダーとデコーダーの使い方

JSON(JavaScript Object Notation)は、軽量なデータ交換フォーマットの一つです。Pythonにはpickleというシリアライズ機構がありますが、pickleのシリアライズ形式はPython固有のものである一方、JSONは多くのプログラミング言語で実装されているため、言語間のデータ交換に広く利用されています。

Pythonの標準ライブラリに含まれるjsonモジュールは、pickleやmarshalモジュールと同様のオブジェクトシリアライズ機能を提供します。pickleモジュールと同じように、dumps()loads()関数を使えばPythonオブジェクトをJSONエンコードされた文字列に変換でき、dump()load()関数を使えばファイルへの書き込み・読み出しが可能です。

dumps()関数

dumps()は、PythonオブジェクトをJSON形式の文字列に変換する関数です。

loads()関数

loads()は、JSON形式の文字列を元のPythonオブジェクトに復元する関数です。

以下の例で基本的な使い方を確認してみましょう。

>>> import json
>>> data=['Rakesh',{'marks':(50,60,70)}]
>>> s=json.dumps(data)
>>> s
'["Rakesh", {"marks": [50, 60, 70]}]'
>>> json.loads(s)
['Rakesh', {'marks': [50, 60, 70]}]

sort_keys引数でキーをソートする

dumps()関数にはオプション引数sort_keysを指定できます。デフォルト値はFalseですが、Trueに設定すると、辞書のキーがソートされた順序でJSON文字列に出力されます。

>>> data={"marks":50, "age":20, "rank":5}
>>> s=json.dumps(data, sort_keys=True)
>>> s
'{"age": 20, "marks": 50, "rank": 5}'
>>> json.loads(s)
{'age': 20, 'marks': 50, 'rank': 5}

indent引数で整形出力する

dumps()関数にはもう一つの便利なオプション引数indentがあります。数値を指定すると、pprintモジュールの出力のように、インデントされた整形済みのJSON文字列が生成されます。値はインデントの幅(スペース数)を決定します。

>>> data = ['Rakesh',{'marks':(50,60,70)}]
>>> s = json.dumps(data, indent=2)
>>> print (s)
[
  "Rakesh",
  {
    "marks": [
      50,
      60,
      70
    ]
  }
]

オブジェクト指向API:JSONEncoderクラスとJSONDecoderクラス

jsonモジュールには、上記の関数に対応するオブジェクト指向APIも用意されています。モジュール内にはJSONEncoderJSONDecoderという2つのクラスが定義されています。

JSONEncoderクラス

JSONEncoderクラスのオブジェクトは、Pythonのデータ構造をエンコードするためのエンコーダーです。各Pythonデータ型は、次の表のように対応するJSON型へ変換されます。

PythonJSON
dictobject
list, tuplearray
strstring
int, float、int/float由来のEnumnumber
Truetrue
Falsefalse
Nonenull

JSONEncoderクラスはJSONEncoder()コンストラクタでインスタンス化します。このクラスで定義されている主なメソッド・属性は以下の通りです。

  • encode() ― PythonオブジェクトをJSON形式にシリアライズします。
  • iterencode() ― オブジェクトをエンコードし、各要素のエンコード結果を順に返すイテレータを返します。
  • indent ― エンコードされた文字列のインデント幅を指定します。
  • sort_keys ― TrueまたはFalseを指定し、キーをソートして出力するかどうかを決定します。
  • check_circular ― Trueの場合、コンテナ型オブジェクト内の循環参照をチェックします。

以下の例では、Pythonのリストオブジェクトをエンコードしています。

>>> e=json.JSONEncoder()
>>> e.encode(data)
'["Rakesh", {"marks": [50, 60, 70]}]'

iterencode()メソッドを使うと、エンコード結果の各部分を順番に取得できます。

>>> for obj in e.iterencode(data):
print (obj)
[
"Rakesh"
{
"marks"
:
[
50
, 60
, 70
]
}
]

JSONDecoderクラス

JSONDecoderクラスのオブジェクトは、JSON文字列をPythonのデータ構造にデコードするために使用します。このクラスの主要メソッドはdecode()です。以下のコードでは、先ほどエンコードした文字列からPythonのリストオブジェクトを復元しています。

>>> d=json.JSONDecoder()
>>> d.decode(s)
['Rakesh', {'marks': [50, 60, 70]}]

ファイルやストリームとのJSONデータのやり取り

jsonモジュールには、ディスク上のファイルやバイトストリームのようなファイルライクなオブジェクトに対して、JSONデータを書き込んだり読み戻したりするためのload()およびdump()関数が定義されています。

dump()関数

dump()は、PythonオブジェクトのデータをJSON形式にエンコードし、ファイルに書き込む関数です。対象のファイルは書き込み権限を持っている必要があります。

>>> data=['Rakesh', {'marks': (50, 60, 70)}]
>>> fp=open('json.txt','w')
>>> json.dump(data,fp)
>>> fp.close()

このコードを実行すると、カレントディレクトリに「json.txt」が作成され、内容は以下のようになります。

["Rakesh", {"marks": [50, 60, 70]}]

load()関数

load()は、ファイルからJSONデータを読み込み、そこからPythonオブジェクトを構築する関数です。ファイルは読み取り権限付きで開く必要があります。

>>> fp=open('json.txt','r')
>>> ret=json.load(fp)
>>> ret
['Rakesh', {'marks': [50, 60, 70]}]
>>> fp.close()

まとめ

本記事では、Pythonのjsonモジュールにおける重要な機能を解説しました。文字列として変換するdumps()/loads()、ファイルと直接やり取りするdump()/load()、そしてより細かい制御が可能なJSONEncoder/JSONDecoderクラスを使い分けることで、JSONデータを柔軟に扱えるようになります。Web APIとの連携や設定ファイルの管理など、さまざまな場面で活用してみてください。

  1. Pythonパッケージの作成からPyPI公開まで完全ガイド|pip・setup.py・twineの使い方

    Pythonには、自作コードをパッケージとして作成・公開するための非常にシンプルな仕組みが用意されています。この記事では、Pythonコードをパッケージ化し、PyPI(Python Package Index)で公開するまでの一連の手順を、初心者にもわかりやすく解説します。Pythonのパッケージ管理ツールPythonのパッケージ管理は、主に以下のツールによって行われます。pip:最も広く使われているパッケージ管理ツールです。OSへの手動インストールや更新作業をほぼ不要にし、パッケージとそのバージョン番号のリストを管理することで、別環境への正確な再現(複製)を可能にします。Python Pac

  2. Pythonの辞書をJSON形式で出力・表示する方法

    JSONとはJSON(JavaScript Object Notation)は、データをテキスト形式で表現するための軽量なデータ交換フォーマットです。Web APIや設定ファイルなど、さまざまな場面で広く利用されています。jsonモジュールとdumps()関数Pythonには標準ライブラリとしてjsonモジュールが用意されており、JSONデータのエンコード(書き出し)とデコード(読み込み)を簡単に行うことができます。このモジュールのdumps()関数を使用すると、Pythonの辞書オブジェクトをそのままJSON形式の文字列に変換できます。基本的な使い方D1={pen:25, pencil:10