Python3.5对象和json.dumps()输出

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

我编写了一个类,允许我在日期(字符串%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(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(今天)
行为的原因并不像乍一看那么明显。要理解这个问题,你应该能够回答两个问题:

  • 包含时间的字符串值从何而来
  • 为什么
    Day.\uuuu str\uuuu
    没有被json编码器调用?应该吗
以下是一些先决条件:

  • 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)))