2022/06/07

pythonにおけるJSONの取り扱い

pythonでのJSON形式ファイルの取り扱いについて
jsonファイルをデータベースの代わりとして簡単にWebサイトを作ろうとした時に調べようと思っていた

前提知識等

pythonの組み込み型について

種類

カッコの形

詳細

リスト

[..., ...]

・番地で要素にアクセス
・要素変更可能
・要素の重複あり

タプル

(..., ...)

・番地で要素にアクセス
・要素変更不可
・要素の重複あり

辞書

{... : ..., ... : ..., ...}

・キーで要素にアクセス
・要素変更可能
・キーの重複なし

jsonモジュールについても知っておく必要がある
今回はjson.dump(), json.load()を使った

コード

import json

JSON_FILE1 = "test1.json"
JSON_FILE2 = "test2.json"

# JSON形式を辞書要素持ちのリストとして読み込み、
# 中身を操作したのちJSON形式に戻して書き込む

def test1():
    # ここで大まかな型なんかを決めているが、結局のところ書き込むときはstr or int?
    """Todoリストのデータを保存する
    :param name: name
    :type name: str
    :param age: age
    :type age: int 
    :param operation: operate
    :type operation: str
    """
    try:
        db1 = json.load(open(JSON_FILE1, mode="r", encoding="utf-8"))
    except FileNotFoundError:
        # ここで空のリストを生成して、その中に要素を追加することでjson形式への変換を可能にする
        db1 = []
    
    db1.append({
        "name": 'sato',
        "age": 21,
        "operation": 'append'
    })
    db1.append({
        "name": 'tanaka',
        "age": 25,
        "operation": 'append'
    })
    db1.insert(1,{
        "name": '佐藤',
        "age": 30,
        "operation": 'insert1'
    })
    # ensure_ascii=Falseをつけないと.jsonファイル内では日本語のデコードはされないが
    # またpythonでファイルをロードしたときにはデコードされている
    json.dump(db1, open(JSON_FILE1, mode="w", encoding="utf-8"), indent=4)
    
    try:
        db2 = json.load(open(JSON_FILE2, mode="r", encoding="utf-8"))
    except FileNotFoundError:
        db2 = []
    
    db2.append({
        "name": 'sato',
        "age": '21',
        "operation": 'append'
    })
    db2.append({
        "name": 'sato',
        "age": '25',
        "operation": 'append'
    })
    db2.insert(0,{
        "name": '佐藤',
        "age": '23',
        "operation": 'insert0'
    })
    json.dump(db2, open(JSON_FILE2, mode="w", encoding="utf-8"), indent=4, ensure_ascii=False)

if __name__ == "__main__":
    print("json形式の書き込みテスト")
    test1()

json_test1.py

生成されたjsonファイル

[
    {
        "name": "sato",
        "age": 21,
        "operation": "append"
    },
    {
        "name": "\u4f50\u85e4",
        "age": 30,
        "operation": "insert1"
    },
    {
        "name": "tanaka",
        "age": 25,
        "operation": "append"
    }
]

test1.json

こちらのファイルはjson.dumpの際にensure_ascii=Falseを記述しなかった
日本語で記述した部分がエンコードされた状態でファイルに保存されている
これだとjsonファイルを直接見てデータを確認するときに不便だが、再度pythonで読み込む際にはデコードされているので、そこは使い方次第

[
    {
        "name": "佐藤",
        "age": "23",
        "operation": "insert0"
    },
    {
        "name": "sato",
        "age": "21",
        "operation": "append"
    },
    {
        "name": "sato",
        "age": "25",
        "operation": "append"
    }
]

test2.json

ageも文字列として書き込んだ
こうなるとpythonで読み込み直した際に演算に手間が生じる

import json

JSON_FILE1 = 'test1.json'
JSON_FILE2 = 'test2.json'

def operate_json():
    try:
        db = json.load(open(JSON_FILE1, mode="r", encoding="utf-8"))
    except:
        db = []
    print(db)
    # 計算もできる
    db[0]["age"] += 1
    print(db)
    # 丸々要素を持ってきて、丸ごと消すのがいいかも。
    remove_db = db[1] # (削除した内容を別の場所に保存できると便利?)
    db.remove(remove_db)
    db.insert(0,remove_db)

    print(db)

    json.dump(db, open(JSON_FILE1, mode="w", encoding="utf-8"), indent=4)    

if __name__ == "__main__":
    print("json形式ファイルを読み込んで操作する")
    operate_json()

json_test2.py

簡単に要素に対する演算と、データ削除、追加のみをおこなっている

実際に使った様子(画像等)

% python json_test2.py
json形式ファイルを読み込んで操作する
[{'name': 'sato', 'age': 21, 'operation': 'append'}, {'name': '佐藤', 'age': 30, 'operation': 'insert1'}, {'name': 'tanaka', 'age': 25, 'operation': 'append'}]
[{'name': 'sato', 'age': 22, 'operation': 'append'}, {'name': '佐藤', 'age': 30, 'operation': 'insert1'}, {'name': 'tanaka', 'age': 25, 'operation': 'append'}]
[{'name': '佐藤', 'age': 30, 'operation': 'insert1'}, {'name': 'sato', 'age': 22, 'operation': 'append'}, {'name': 'tanaka', 'age': 25, 'operation': 'append'}]

json_test2.py実行の様子

まとめ

これくらいの操作ができればある程度のものを実装することができると思う
問題は、JSONファイルのデータ構造をどうするか
データベースのようなものを考えるなら
[[ID, {key:element, key2...}], [ID, {key:element, key2....}]]
IDの最大値をとってそれ+1の値を次のIDにできる
for文を使ってIDの値の要素を見つけ

for i in range(len(jsondata)):
    # IDが10の要素を発見->この時のiがjsondata内のindexであることがわかる
    if jsondata[i][0]==10
        operate(jsondata[i]) # removeなど

でできるかな?

検索用タグ

python, json

参考