解析 python json 加载中的日期时间

ksr*_*ini 4 javascript python datetime json

我想解析 (json.loads) 一个 json 字符串,其中包含从 http 客户端发送的日期时间值。

我知道我可以通过扩展默认编码器并覆盖默认方法来编写自定义 json 编码器

class MyJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.datetime,)):
            return obj.isoformat()
        elif isinstance(obj, (decimal.Decimal,)):
            return str(obj)
        else:
            return json.JSONEncoder.default(self, obj)
Run Code Online (Sandbox Code Playgroud)

我的问题是 -

  1. 如何自定义默认的 json 解码器?我需要重写解码方法吗?我可以以某种方式为 json 字符串中的每个字段/值覆盖/添加回调函数吗?(我已经看到了 json.decoder.JSONDecoder 和 json.scanner 中的代码,但不知道该怎么做)
  2. 有没有一种简单的方法可以将特定值识别为日期时间字符串?日期值是 ISO 格式的字符串。

谢谢,

Mau*_*use 7

可能还有其他解决方案,但是json.load&json.loads都采用每个解析对象调用的object_hook参数1,其返回值用于代替最终结果中提供的对象。

将其与对象中的一个小标签相结合,这样的事情是可能的;

import json
import datetime
import dateutil.parser
import decimal

CONVERTERS = {
    'datetime': dateutil.parser.parse,
    'decimal': decimal.Decimal,
}


class MyJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.datetime,)):
            return {"val": obj.isoformat(), "_spec_type": "datetime"}
        elif isinstance(obj, (decimal.Decimal,)):
            return {"val": str(obj), "_spec_type": "decimal"}
        else:
            return super().default(obj)


def object_hook(obj):
    _spec_type = obj.get('_spec_type')
    if not _spec_type:
        return obj

    if _spec_type in CONVERTERS:
        return CONVERTERS[_spec_type](obj['val'])
    else:
        raise Exception('Unknown {}'.format(_spec_type))


def main():
    data = {
        "hello": "world",
        "thing": datetime.datetime.now(),
        "other": decimal.Decimal(0)
    }
    thing = json.dumps(data, cls=MyJSONEncoder)

    print(json.loads(thing, object_hook=object_hook))

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)