How to overcome “datetime.datetime not JSON serializable”?

后端 未结 30 2681
梦谈多话
梦谈多话 2020-11-22 03:31

I have a basic dict as follows:

sample = {}
sample[\'title\'] = \"String\"
sample[\'somedate\'] = somedatetimehere


        
相关标签:
30条回答
  • 2020-11-22 03:57

    Here is my full solution for converting datetime to JSON and back..

    import calendar, datetime, json
    
    def outputJSON(obj):
        """Default JSON serializer."""
    
        if isinstance(obj, datetime.datetime):
            if obj.utcoffset() is not None:
                obj = obj - obj.utcoffset()
    
            return obj.strftime('%Y-%m-%d %H:%M:%S.%f')
        return str(obj)
    
    def inputJSON(obj):
        newDic = {}
    
        for key in obj:
            try:
                if float(key) == int(float(key)):
                    newKey = int(key)
                else:
                    newKey = float(key)
    
                newDic[newKey] = obj[key]
                continue
            except ValueError:
                pass
    
            try:
                newDic[str(key)] = datetime.datetime.strptime(obj[key], '%Y-%m-%d %H:%M:%S.%f')
                continue
            except TypeError:
                pass
    
            newDic[str(key)] = obj[key]
    
        return newDic
    
    x = {'Date': datetime.datetime.utcnow(), 34: 89.9, 12.3: 90, 45: 67, 'Extra': 6}
    
    print x
    
    with open('my_dict.json', 'w') as fp:
        json.dump(x, fp, default=outputJSON)
    
    with open('my_dict.json') as f:
        my_dict = json.load(f, object_hook=inputJSON)
    
    print my_dict
    

    Output

    {'Date': datetime.datetime(2013, 11, 8, 2, 30, 56, 479727), 34: 89.9, 45: 67, 12.3: 90, 'Extra': 6}
    {'Date': datetime.datetime(2013, 11, 8, 2, 30, 56, 479727), 34: 89.9, 45: 67, 12.3: 90, 'Extra': 6}
    

    JSON File

    {"Date": "2013-11-08 02:30:56.479727", "34": 89.9, "45": 67, "12.3": 90, "Extra": 6}
    

    This has enabled me to import and export strings, ints, floats and datetime objects. It shouldn't be to hard to extend for other types.

    0 讨论(0)
  • 2020-11-22 03:58

    You should use .strftime() method on .datetime.now() method to making it as a serializable method.

    Here's an example:

    from datetime import datetime
    
    time_dict = {'time': datetime.now().strftime('%Y-%m-%dT%H:%M:%S')}
    sample_dict = {'a': 1, 'b': 2}
    sample_dict.update(time_dict)
    sample_dict
    

    Output:

    Out[0]: {'a': 1, 'b': 2, 'time': '2017-10-31T15:16:30'}
    
    0 讨论(0)
  • 2020-11-22 03:58

    If you are using the result in a view be sure to return a proper response. According to the API, jsonify does the following:

    Creates a Response with the JSON representation of the given arguments with an application/json mimetype.

    To mimic this behavior with json.dumps you have to add a few extra lines of code.

    response = make_response(dumps(sample, cls=CustomEncoder))
    response.headers['Content-Type'] = 'application/json'
    response.headers['mimetype'] = 'application/json'
    return response
    

    You should also return a dict to fully replicate jsonify's response. So, the entire file will look like this

    from flask import make_response
    from json import JSONEncoder, dumps
    
    
    class CustomEncoder(JSONEncoder):
        def default(self, obj):
            if set(['quantize', 'year']).intersection(dir(obj)):
                return str(obj)
            elif hasattr(obj, 'next'):
                return list(obj)
            return JSONEncoder.default(self, obj)
    
    @app.route('/get_reps/', methods=['GET'])
    def get_reps():
        sample = ['some text', <datetime object>, 123]
        response = make_response(dumps({'result': sample}, cls=CustomEncoder))
        response.headers['Content-Type'] = 'application/json'
        response.headers['mimetype'] = 'application/json'
        return response
    
    0 讨论(0)
  • 2020-11-22 03:58

    I got the same error message while writing the serialize decorator inside a Class with sqlalchemy. So instead of :

    Class Puppy(Base):
        ...
        @property
        def serialize(self):
            return { 'id':self.id,
                     'date_birth':self.date_birth,
                      ...
                    }
    

    I simply borrowed jgbarah's idea of using isoformat() and appended the original value with isoformat(), so that it now looks like:

                      ...
                     'date_birth':self.date_birth.isoformat(),
                      ...
    
    0 讨论(0)
  • 2020-11-22 03:59

    I have just encountered this problem and my solution is to subclass json.JSONEncoder:

    from datetime import datetime
    import json
    
    class DateTimeEncoder(json.JSONEncoder):
        def default(self, o):
            if isinstance(o, datetime):
                return o.isoformat()
    
            return json.JSONEncoder.default(self, o)
    

    In your call do something like: json.dumps(yourobj, cls=DateTimeEncoder) The .isoformat() I got from one of the answers above.

    0 讨论(0)
  • 2020-11-22 03:59

    You have to supply a custom encoder class with the cls parameter of json.dumps. To quote from the docs:

    >>> import json
    >>> class ComplexEncoder(json.JSONEncoder):
    ...     def default(self, obj):
    ...         if isinstance(obj, complex):
    ...             return [obj.real, obj.imag]
    ...         return json.JSONEncoder.default(self, obj)
    ...
    >>> dumps(2 + 1j, cls=ComplexEncoder)
    '[2.0, 1.0]'
    >>> ComplexEncoder().encode(2 + 1j)
    '[2.0, 1.0]'
    >>> list(ComplexEncoder().iterencode(2 + 1j))
    ['[', '2.0', ', ', '1.0', ']']
    

    This uses complex numbers as the example, but you can just as easily create a class to encode dates (except I think JSON is a little fuzzy about dates)

    0 讨论(0)
提交回复
热议问题