【问题标题】:Parsing datetime in python json loads在python json加载中解析日期时间
【发布时间】:2015-08-30 15:37:46
【问题描述】:

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

我知道我可以通过扩展默认编码器并覆盖默认方法来编写自定义 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)

我的问题是 -

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

谢谢,

【问题讨论】:

    标签: javascript python json datetime


    【解决方案1】:

    可能还有其他解决方案,但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()
    

    【讨论】:

    • 谢谢多米尼克。这就说得通了。我正在考虑创建一个具有“类型”属性的对象,但没有注意到 object_hook 参数。
    【解决方案2】:

    至于第二个问题,您应该只使用

    import dateutil.parser dateutil.parser.parse('Your string')

    方法,它会尝试解析你的日期字符串,如果它无法识别它,它会抛出值错误。您还可以使用正则表达式来查找至少看起来像日期的字段(当然取决于您使用的格式)

    【讨论】:

    • 您是否建议我将正则表达式应用于所有值?我需要遍历从 json 字符串获得的整个 dict 以在每个值上应用正则表达式?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多