【Python】Python ~ 基本編 / JSONあれこれ ~

■ はじめに

https://dk521123.hatenablog.com/entry/2019/10/19/104805

の続き。

JSONに関して扱うことになったので、メモ。

目次

【1】JSONインスタンスをコピーする
【2】JSONをマージする
【3】JSONオブジェクトをフィルタリングする
【4】SELECTした結果をJSON化
 1)PostgreSQLの場合
【5】エラー「TypeError: Object of type datetime is not JSON serializable」対策

【1】JSONインスタンスをコピーする

<json>.copy() を使う

サンプル

import json

input_dict = {"name": "Smith", "birth_day": "2002-12-21", "gender": "man"}
clone_dict = input_dict.copy()
clone_dict["name"] = "Mike"

# {'name': 'Smith', 'birth_day': '2002-12-21', 'gender': 'man'}
print(input_dict)
# {'name': 'Mike', 'birth_day': '2002-12-21', 'gender': 'man'}
print(clone_dict)

【2】JSONをマージする

<json1>.update(<json2>) を使う

※ キーが重複する場合

⇒ 引数 <json2> で上書きされる

サンプル

import json

input1_dict = {"name": "Smith", "birth_day": "1967-08-11", "gender": "man"}
input2_dict = {"birth_day": "2012-12-23", "occupation": "IT", "note": "Hello world"}
input1_dict.update(input2_dict)

# {'name': 'Smith', 'birth_day': '2012-12-23', 'gender': 'man', 'occupation': 'IT', 'note': 'Hello world'}
print(input1_dict)

【3】JSONオブジェクトをフィルタリングする

* lambda / filter を使うといいかも。

https://stackoverflow.com/questions/40827356/find-a-value-in-json-using-python/40827383

サンプル

例1:lambda / filterでフィルタリング

user_list = [
  {
    "id": "X0001",
    "name": "Mike",
    "birth_date": None
  },
  {
    "id": "X0002",
    "name": "Tom",
    "birth_date": "2022-01-01"
  },
  {
    "id": "X0003",
    "name": "Paul",
    "birth_date": "1988-12-12"
  }
]

results = list(filter(lambda x: x["id"] == "X0003", user_list))

# [{'id': 'X0003', 'name': 'Paul', 'birth_date': '1988-12-12'}]
print(results)

例2:汎用的に使えるように関数化

def find(target_list: list, filter_dict: dict):
  return_values = target_list
  for key, value in filter_dict.items():
    return_values = list(filter(lambda x: x[key] == value, return_values))
  return return_values

user_list = [
  {
    "id": "X0001",
    "name": "Mike",
    "birth_date": None
  },
  {
    "id": "X0002",
    "name": "Tom",
    "birth_date": "2022-01-01"
  },
  {
    "id": "X0003",
    "name": "Paul",
    "birth_date": "1988-12-12"
  },
  {
    "id": "X0004",
    "name": "Mike",
    "birth_date": "1988-12-12"
  },
  {
    "id": "X0005",
    "name": "Paul",
    "birth_date": "1988-12-12"
  },
]

results = find(user_list, {"name": "Mike", "birth_date": "1988-12-12"})

# [{'id': 'X0004', 'name': 'Mike', 'birth_date': '1988-12-12'}]
print(results)

【4】SELECTした結果をJSON

1)PostgreSQLの場合

* 以下の関連記事を参照のこと

PythonPostgreSQL を使う ~ psycopg2編 ~
https://dk521123.hatenablog.com/entry/2020/05/06/141029

【5】エラー「TypeError: Object of type datetime is not JSON serializable」対策

* 以下のコードを実行するとエラー

エラーが発生するコード

import json
from datetime import datetime

now = datetime.now()
input_json = { "created_at": now, "user": "Mike" }
print(json.dumps(input_json))

エラー詳細

TypeError: Object of type datetime is not JSON serializable

解決案

* 以下が参考になった

https://sebhastian.com/object-of-type-datetime-is-not-json-serializable/
https://www.bioerrorlog.work/entry/python-datetime-not-json-serializable-error
案1:default=strを付与

print(json.dumps(input_json, default=str))
# {"created_at": "2023-10-31 20:07:54.386454", "user": "Mike"}

案2:datetime => string に変換

now = datetime.now().strftime("%Y-%m-%d")

print(json.dumps(input_json)
# {"created_at": "2023-10-31", "user": "Mike"}

案3:カスタム変換をかませる

import json
from datetime import date, datetime

def custom_json_serial(obj):
  if isinstance(obj, (datetime, date)):
    return obj.isoformat()
  raise TypeError (f'Type {obj} not serializable')

now = datetime.now()
input_json = { "created_at": now, "user": "Mike" }
print(json.dumps(input_json, default=custom_json_serial))
# {"created_at": "2023-10-31T20:14:36.145797", "user": "Mike"}

関連記事

Python ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2019/10/12/075251
Python ~ 基本編 / JSON
https://dk521123.hatenablog.com/entry/2019/10/19/104805
Python ~ 基本編 / YAML
https://dk521123.hatenablog.com/entry/2019/10/16/225401
Python ~ 基本編 / ラムダ lambda ~
https://dk521123.hatenablog.com/entry/2019/09/23/000000
Python ~ 基本編 / map ~
https://dk521123.hatenablog.com/entry/2021/03/29/000000
Python ~ 基本編 / 辞書 ~
https://dk521123.hatenablog.com/entry/2019/10/27/100014
Python ~ 基本編 / 辞書・あれこれ ~
https://dk521123.hatenablog.com/entry/2020/10/11/000000
PythonPostgreSQL を使う ~ psycopg2編 ~
https://dk521123.hatenablog.com/entry/2020/05/06/141029
Pandas ~ 基本編 / JSON編 ~
https://dk521123.hatenablog.com/entry/2022/02/16/000000
Python ~ ndjson を扱う ~
https://dk521123.hatenablog.com/entry/2022/08/30/224248