Python3.5对象和json.dumps()输出
我编写了一个类,允许我在日期(字符串%Y-%m-%d)中添加天数(整数)。此类的对象需要是JSON可序列化的 将天数以整数的形式添加到我的对象中,效果与预期一样。但是,json.dumps(obj)为我的原始对象返回了太多的信息(“2016-03-23 15:57:47.926362”)为什么?我需要如何修改类以获得“2016-03-23”?请参见下面的示例 代码:Python3.5对象和json.dumps()输出,python,json,class,datetime,python-3.5,Python,Json,Class,Datetime,Python 3.5,我编写了一个类,允许我在日期(字符串%Y-%m-%d)中添加天数(整数)。此类的对象需要是JSON可序列化的 将天数以整数的形式添加到我的对象中,效果与预期一样。但是,json.dumps(obj)为我的原始对象返回了太多的信息(“2016-03-23 15:57:47.926362”)为什么?我需要如何修改类以获得“2016-03-23”?请参见下面的示例 代码: from datetime import datetime, timedelta import json class Day(s
from datetime import datetime, timedelta
import json
class Day(str):
def __init__(self, _datetime):
self.day = _datetime
def __str__(self):
return self.day.date().isoformat()
def __repr__(self):
return "%s" % self.day.date().isoformat()
def __add__(self, day):
new_day = self.day + timedelta(days=day)
return Day(new_day).__str__()
def __sub__(self, day):
new_day = self.day - timedelta(days=day)
return Day(new_day).__str__()
if __name__ == "__main__":
today = Day(datetime.today())
print(today) # 2016-03-23
print(json.dumps(today)) # "2016-03-23 15:57:47.926362"
print(today+1) # 2016-03-24
print(json.dumps(today+1)) # "2016-03-24"
print(today-1) # 2016-03-22
print(json.dumps(today-1)) # "2016-03-22"
更新。以下是我为感兴趣的人编写的最终代码:
from datetime import datetime, timedelta
import json
class Day(str):
def __init__(self, datetime_obj):
self.day = datetime_obj
def __new__(self, datetime):
return str.__new__(Day, datetime.date().isoformat())
def __add__(self, day):
new_day = self.day + timedelta(days=day)
return Day(new_day)
def __sub__(self, day):
new_day = self.day - timedelta(days=day)
return Day(new_day)
if __name__ == "__main__":
today = Day(datetime.today())
print(type(today))
print(today) # 2016-03-23
print(json.dumps(today)) # "2016-03-23"
print(today + 1) # 2016-03-24
print(json.dumps(today + 1)) # "2016-03-24"
print(today - 1) # 2016-03-22
print(json.dumps(today - 1)) # "2016-03-22"
print(json.dumps(dict(today=today))) # {"today": "2016-03-23"}
print(json.dumps(dict(next_year=today+365))) # {"next_year": "2017-03-23"}
print(json.dumps(dict(last_year=today-366))) # {"last_year": "2015-03-23"}
酷!让我们开始吧。你正在看到:
print(json.dumps(today)) # "2016-03-23 15:57:47.926362"
因为在编码过程中,当决定如何序列化传递给它的内容时,json.dump
在对象上调用isinstance(…,str)
。这将返回True
,并且对象被序列化,就像这个字符串一样
但是“2016-03-23 15:57:47.926362”
值从何而来
当您调用day=day(datetime\u obj)
时,会发生两件事:
来实例化对象。您没有提供\uuuuuu new\uuuu
方法,因此使用了\uuuuu new\uuuu
str.\uuuuu new\uuu
- 调用
初始化对象\uuuu init\uuuu
day=day(datetime\u obj)
有效地转换为:
day = str.__new__(Day, datetime_obj)
对于json.dumps
,您的对象将是str
,但是str
的值被设置为默认的字符串表示形式datetime\u obj
。这恰好是您看到的完整格式。内置,伙计
我一直在玩这个游戏,如果你玩你自己的\uuuuuuuuuuuuuuuuuuuuuuuuuu
(这是一个稍微令人兴奋的领域,小心踩)来拦截str.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
class Day(str):
def __new__(self, datetime):
return str.__new__(Day, datetime.date().isoformat())
但如果整件事都着火了,你就没听我说
PS子类jsonecoder
的正确方法。但是它没有任何乐趣
PS2噢,天哪,我在2.7
上测试了这个。我可能完全在那里,如果我在,就给我一个徽章。json.dumps(今天)
行为的原因并不像乍一看那么明显。要理解这个问题,你应该能够回答两个问题:
- 包含时间的字符串值从何而来
- 为什么
没有被json编码器调用?应该吗Day.\uuuu str\uuuu
datetime.today()
方法类似于datetime.now()
——它包括当前时间(小时、分钟等)。您可以使用date.today()
,仅获取日期。str
在Python中创建不可变对象;它的值在未重写的\uuuu new\uuuu
方法中设置,因此默认转换为str(datetime.today())
用于将日期
的值初始化为字符串。它创建的字符串值在您的案例中同时包含日期和时间。您可以覆盖\uuuuuuuu新的,以获得不同的字符串值
:
def __new__(cls, _datetime):
return str.__new__(cls, _datetime.date())
Day
是str
子类,因此其实例被编码为JSON字符串str
方法返回str
对象,而不是相应的子类对象,除非您重写它们,例如:
>>> class S(str):
... def duplicate(self):
... return S(self * 2)
...
>>> s = S('abc')
>>> s.duplicate().duplicate()
'abcabcabcabc'
>>> s.upper().duplicate()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'duplicate'
相关Python问题:请注意,如果从
\uuuu add\uuuuu
和\uuuu sub\uuuuuu
中删除\uu str\uuuuuuuuuuuuuuuuuu()
中的,则您的结果会更加一致。但是我如何从结果中删除时间呢?无关:1-您应该从\uuuuuuu add\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>中删除,(例如,支持今天+1+1
)2-不要覆盖str.\uuuu str.\uuuuu
,而是覆盖str.\uuu new.\uuuuuu
来自定义字符串表示。这就是我最后做的。谢谢!你是个明星!我尝试过new,但运气不好。我编辑的建议代码中有一个错误。你的答案确实是一个很好的解释。谢谢!
import json
for suffix in ['', '_ascii']:
function_name = 'encode_basestring' + suffix
orig_function = getattr(json.encoder, function_name)
setattr(json.encoder, function_name, lambda s,_e=orig_function: _e(str(s)))