如何使用JSON.loads转换为Python datetime对象?

ozg*_*gur 31 python datetime json

我有一个JSON对象的字符串表示形式.

dumped_dict = '{"debug": false, "created_at": "2020-08-09T11:24:20"}'
Run Code Online (Sandbox Code Playgroud)

当我用这个对象调用json.loads时;

json.loads(dumped_dict)
Run Code Online (Sandbox Code Playgroud)

我明白了

{'created_at': '2020-08-09T11:24:20', 'debug': False}
Run Code Online (Sandbox Code Playgroud)

这里没有错.但是,我想知道是否有办法将上面的对象与json.loads转换为如下所示:

{'created_at': datetime.datetime(2020, 08, 09, 11, 24, 20), 'debug': False}
Run Code Online (Sandbox Code Playgroud)

不久,我们能够在调用json.loads时将datetime字符串转换为实际的datetime.datetime对象吗?

Nic*_*cci 22

到目前为止我的解

>>> json_string = '{"last_updated": {"$gte": "Thu, 1 Mar 2012 10:00:49 UTC"}}'
>>> dct = json.loads(json_string, object_hook=datetime_parser)
>>> dct
{u'last_updated': {u'$gte': datetime.datetime(2012, 3, 1, 10, 0, 49)}}


def datetime_parser(dct):
    for k, v in dct.items():
        if isinstance(v, basestring) and re.search("\ UTC", v):
            try:
                dct[k] = datetime.datetime.strptime(v, DATE_FORMAT)
            except:
                pass
    return dct
Run Code Online (Sandbox Code Playgroud)

有关使用object_hook的进一步参考:JSON编码器和解码器

在我的例子中,json字符串来自对我的REST API的GET请求.__date__只要输入字符串符合DATE_FORMAT,这个解决方案允许我透明地"正确地获取日期",而不会强迫客户端和用户输入硬编码前缀,例如:

DATE_FORMAT = '%a, %d %b %Y %H:%M:%S UTC'
Run Code Online (Sandbox Code Playgroud)

应该进一步细化正则表达式模式

PS:如果你想知道,json_string是一个MongoDB/PyMongo查询.

  • 请提供一些反馈/建议而不是简单的 -1,这样我至少可以学到一些东西:) (2认同)

gal*_*ant 17

你需要传递一个object_hook.从文档:

object_hook是一个可选函数,将使用任何对象文字解码(dict)的结果调用.将使用object_hook的返回值而不是dict.

像这样:

import datetime
import json

def date_hook(json_dict):
    for (key, value) in json_dict.items():
        try:
            json_dict[key] = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
        except:
            pass
    return json_dict

dumped_dict = '{"debug": false, "created_at": "2020-08-09T11:24:20"}'
loaded_dict = json.loads(dumped_dict, object_hook=date_hook)
Run Code Online (Sandbox Code Playgroud)

如果你还想处理时区,你必须使用dateutil而不是strptime.

  • 使用 try/catch 作为控制结构并不理想。 (4认同)

Mic*_*ner 9

虽然从技术上来说它只是提供一个对象钩子函数,但我建议使用JSONDecoder框架开发人员想要的适当的子类:

class _JSONDecoder(json.JSONDecoder):
    def __init__(self, *args, **kwargs):
        json.JSONDecoder.__init__(
            self, object_hook=self.object_hook, *args, **kwargs)

    def object_hook(self, obj):
        ret = {}
        for key, value in obj.items():
            if key in {'timestamp', 'whatever'}:
                ret[key] = datetime.fromisoformat(value) 
            else:
                ret[key] = value
        return ret
Run Code Online (Sandbox Code Playgroud)

为了完整起见,这里是解码器的对应部分,即自定义 JSONEncoder:

class _JSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime, pd.Timestamp)):
            return obj.isoformat()
        return json.JSONEncoder.default(obj)
Run Code Online (Sandbox Code Playgroud)

两者的实际效果如下:

json_str = json.dumps({'timestamp': datetime.datetime.now()}, cls=_JSONEncoder)
d = json.loads(json_str, cls=_JSONDecoder)
Run Code Online (Sandbox Code Playgroud)


Uri*_*lit 7

我会按照尼古拉的建议做同样的事情,但有两处改变:

  1. 使用dateutil.parser而不是datetime.datetime.strptime
  2. 明确定义我想要捕获哪些异常。我通常建议不惜一切代价避免空置except:

或者在代码中:

import dateutil.parser

def datetime_parser(json_dict):
    for (key, value) in json_dict.items():
        try:
            json_dict[key] = dateutil.parser.parse(value)
        except (ValueError, AttributeError):
            pass
    return json_dict

str = "{...}"  # Some JSON with date
obj = json.loads(str, object_hook=datetime_parser)
print(obj)
Run Code Online (Sandbox Code Playgroud)