LoginSignup
0
0

PythonのJSONでkeyにintを使うとデータが飛ぶ

Last updated at Posted at 2024-06-22

はじめに

JSONって便利ですよね
でもちょっと扱いを間違えると場合によっては上書きでデータが飛んでしまったり...

本題

問題です。

data = {2024: "令和6年"}

というdict型のデータがあったとします。
ここで、

print(data[2024])

を実行したら何が表示されるでしょうか?

...簡単ですね。

令和6年

です。

JSON化して保存する

データが出来上がったので保存します。

import json

data = {2024: "令和6年"}
with open("data.json", mode="w") as f:
    f.write(json.dumps(data))

保存したJSONを利用する

出来上がったデータを読み込んで西暦2024年が和暦何年なのかを参照します。

with open("data.json") as f:
    data = json.loads(f.read())
print("西暦2024年は、和暦"+data[2024]+"です。") # KeyError: 2024

エラーが発生してしまいました。

どうして?

元のデータと比較してみます。

import json

data = {2024: "令和6年"}
print(data) # {2024: '令和6年'}
data = json.loads(json.dumps(data))
print(data) # {'2024': '令和6年'}

見て分かる通り、一度JSONにするとint型のkeyは自動的にstr型に変換されてしまいます。

もしも存在しない場合に自動生成される仕様だと...

試しに簡易的なユーザー情報で試してみます。

import json

default_userdata = {"name": "ゲストユーザー"}
users = {1: {"name": "テストユーザー"}}
user_id = 1

# 模擬的な保存 & ロード処理
users = json.loads(json.dumps(users))

if not user_id in users:
    users[user_id] = default_userdata

print(users[user_id]) # デフォルトで上書きされ、 {'name': 'ゲストユーザー'} が出力される

上書きされてしまいました。

じゃあどうするのか

当たり前ですが、JSON以外の方法で保存するか、keyをstrとして扱えばこの問題は防げます。

import json

default_userdata = {"name": "ゲストユーザー"}
users = {"1": {"name": "テストユーザー"}}
user_id = "1"

# 模擬的な保存 & ロード処理
users = json.loads(json.dumps(users))

if not user_id in users:
    users[user_id] = default_userdata

print(users[user_id]) # 正常に {'name': 'テストユーザー'} が出力される

さいごに

かなりやりがちなことですが、この仕様はあまり知られていません。
既に運用しているシステムに跡付けする形でこんな感じにプログラムするとデータが飛んでしまいます。
バックアップがあれば復元できますが、無ければ取り返しがつかないことになってしまいます。

短い記事でしたが、これでJSONのkeyにintを使うことの危険性が伝わったと思います。
今後の開発で参考になればと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0