format.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. # 【主流程 8.3 的辅助转换】MCP 数据库查询结果含有日期、时间或 Decimal 时调用。
  2. # 先在查询方法中用 default_encoder 逐字段转换,再由 json.dumps/DateEncoder 完成序列化。
  3. """
  4. 需求:实现数据格式化工具,处理日期、时间和数值类型的序列化
  5. 思路步骤:
  6. 1. 导入必要的模块和库
  7. 2. 实现default_encoder函数(格式化单个对象)
  8. 3. 创建DateEncoder类(自定义JSON编码器,处理非标准类型序列化)
  9. 4. 重写DateEncoder.default方法(处理序列化时的默认对象转换)
  10. """
  11. import json
  12. from datetime import date, datetime, timedelta
  13. from decimal import Decimal
  14. def default_encoder(obj): # 定义编码器方法,用于格式化单个对象
  15. # 【转换内部步骤 1】datetime 是 date 的子类,先判断 datetime 才能保留时分秒。
  16. # 这些判断是互斥返回分支:命中一种类型就 return,不会继续依次转换所有类型。
  17. # 输入 obj 是某一列值,不是整条结果列表;输出是转换后的单个值。
  18. # 日期对象用 strftime 格式化,时间差用 str,Decimal 用 float;普通 JSON 可处理的值原样返回。
  19. if isinstance(obj, datetime): # 检查是否为datetime,返回带时间的格式化字符串
  20. # %Y/%m/%d 分别是年/月/日,%H/%M/%S 是时/分/秒;格式化结果是字符串。
  21. return obj.strftime('%Y-%m-%d %H:%M:%S')
  22. if isinstance(obj, date): # 检查是否为date,返回日期格式化字符串
  23. return obj.strftime('%Y-%m-%d')
  24. if isinstance(obj, timedelta): # 检查是否为timedelta,转换为字符串
  25. return str(obj)
  26. if isinstance(obj, Decimal): # 检查是否为Decimal,转换为浮点数
  27. # TODO 更优的方案 str(obj)
  28. return float(obj)
  29. return obj # 否则返回原对象
  30. # 定义自定义JSON编码器类,继承自json.JSONEncoder,用于处理非标准类型序列化
  31. class DateEncoder(json.JSONEncoder):
  32. def default(self, obj): # 重写default方法,处理序列化时的默认对象转换
  33. # 【转换内部步骤 2】json.dumps 遇到默认无法编码的对象时才回调此方法。
  34. # 仍不支持的类型交给父类报错;Decimal 当前转为 float,可能损失精度。
  35. # 此类继承 json.JSONEncoder;传给 json.dumps(cls=DateEncoder) 后,框架才会按需调用 default。
  36. # super().default(obj) 保留父类对未知类型的报错行为,避免静默把无法编码的值变成不明确内容。
  37. if isinstance(obj, (date, datetime)): # 检查对象是否为date或datetime类型,对于datetime返回带时间的字符串,对于date返回日期字符串
  38. return obj.strftime('%Y-%m-%d %H:%M:%S') if isinstance(obj, datetime) else obj.strftime('%Y-%m-%d')
  39. if isinstance(obj, timedelta): # 检查对象是否为timedelta类型,将时间差转换为字符串
  40. return str(obj)
  41. if isinstance(obj, Decimal): # 检查对象是否为Decimal类型,将Decimal转换为浮点数以兼容JSON
  42. return float(obj)
  43. return super().default(obj) # 对于其他类型,调用父类默认方法