概要
Pythonのjson.dumps()
とjson.loads()
について、注意点を2点整理してみました。
以下のコードをサンプルとして進めます。
import json
#1
data = {}
data['sample_id'] = 'test'
sample_id = json.dumps(data['sample_id'])
print(data)
print(sample_id)
#2
data = {}
data['sample_id'] = 'test'
sample_id = data['sample_id']
print(data)
print(sample_id)
こちらを実行すると結果は以下の通り。
{'sample_id': 'test'}
"test"
{'sample_id': 'test'}
test
あれ、#1
では"test"
というようにダブルクオーテーションで囲まれているのに対して、#2
ではtest
というようにダブルクオーテーションがありません。
テストコードを書いているときに、プログラム側となぜか結果が異なるなぁ...と思っていたら理由はjson.dumps
にありました。
注意点1:JSON形式にエンコードしているかどうかで変わる
#1
では、JSON形式の文字列に変換(=エンコード)しているのでダブルクォーテーションで囲まれた文字列が出力されます。(これはデフォルトの挙動。なぜ?というと...JSONの仕様がJavaScriptのオブジェクト表記を採用しているからでしょう)
一方、#2
では、単純に文字列を別の変数にコピーしているので、ダブルクォーテーションは付与されません。
json.loads()
でデコードするときに影響が出る
これがどんな点に影響が出るのか?というと、json.loads()
を使ってPythonのデータ構造に変換するとき、つまり辞書型に戻す(=デコード)するときです。
json.loads()
は、渡された文字列が JSON 形式でない場合にエラーが出るので、たとえば以下のコードで実行すると#2
の一番最後のprint
文でエラーになります。
import json
#1
data = {}
data["sample_id"] = "test"
sample_id = json.dumps(data["sample_id"])
print(data)
print(sample_id)
test = json.loads(sample_id)
print(test)
#2
data = {}
data["sample_id"] = "test"
sample_id = data["sample_id"]
print(data)
print(sample_id)
test = json.loads(sample_id)
print(test)
実行結果は以下の通り。
{'sample_id': 'test'}
"test"
test
{'sample_id': 'test'}
test
Traceback (most recent call last):
##略##
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
上述の通り、json.dumps
を使っていない場合は単なる文字列なので、JSONDecodeError
になります。
文字通り、デコードに失敗したエラー、ということがわかりますね。
data
は結果も型も同じように出力されますが、エンコード・デコードの処理が入るのでJSON形式であるかどうかが大事になります。テストコードとか書くときなどはprint
結果だけ見ていると要注意だなと思いました。
注意点2:Noneとnull
最後に、エンコード・デコード時のNone
とnull
について。
以下のコードを叩いてみます。
import json
dict_data = {"samples": {"key1": "value1", "key2": "value2", "key3": None}}
json_data = json.dumps(dict_data)
print(json_data)
dict_data = json.loads(json_data)
print(dict_data)
結果は以下。
{"samples": {"key1": "value1", "key2": "value2", "key3": null}}
{'samples': {'key1': 'value1', 'key2': 'value2', 'key3': None}}
json.dumps()
関数は、JSON形式の文字列に変換するとき、PythonのNone
値はJSONのnull
としてシリアライズされます。逆に、json.loads()
関数は、Pythonオブジェクトに戻すとき、PythonのNone
に変換されます。
ここもPythonでjsonを扱う際には要注意ポイントですね。