I have a basic dict as follows:
sample = {}
sample[\'title\'] = \"String\"
sample[\'somedate\'] = somedatetimehere
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.
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'}
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
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(),
...
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.
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)