Decimal cannot be json.dumps()
caimaoy opened this issue · comments
Yue Chen commented
I cannot return the result of db search which contain the type of Decimal
directly.
My solution is like this:
class EnhancedJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
ARGS = ('year', 'month', 'day', 'hour', 'minute',
'second', 'microsecond')
return {'__type__': 'datetime.datetime',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.date):
ARGS = ('year', 'month', 'day')
return {'__type__': 'datetime.date',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.time):
ARGS = ('hour', 'minute', 'second', 'microsecond')
return {'__type__': 'datetime.time',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, datetime.timedelta):
ARGS = ('days', 'seconds', 'microseconds')
return {'__type__': 'datetime.timedelta',
'args': [getattr(obj, a) for a in ARGS]}
elif isinstance(obj, decimal.Decimal):
'''
return {'__type__': 'decimal.Decimal',
'args': [str(obj),]}
'''
return float(obj)
else:
return super().default(obj)
class EnhancedJSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
super(EnhancedJSONDecoder, self).__init__(*args, object_hook=self.object_hook,
**kwargs)
def object_hook(self, d):
if '__type__' not in d:
return d
o = sys.modules[__name__]
for e in d['__type__'].split('.'):
o = getattr(o, e)
args, kwargs = d.get('args', ()), d.get('kwargs', {})
return o(*args, **kwargs)
def execute_select_sql(sql):
"""excute SELECT SQL """
try:
db = get_db_connect()
cursor = db.cursor()
print 'execute sql is [{}]'.format(sql)
cursor.execute(sql)
data = cursor.fetchall()
try:
json_data = json.dumps(data, cls=EnhancedJSONEncoder)
data = json.loads(json_data, cls=EnhancedJSONDecoder)
except UnicodeDecodeError as e:
data = 'Don not select BLOB!!!'
except Exception as e:
data = repr(e)
except Exception as e:
print repr(e)
raise e
else:
print 'data is [{}]'.format(data)
return data
finally:
try:
db.close()
except:
pass
@jsonrpc.method('run_sql')
def run_sql(sql):
return execute_select_sql(sql)
Nycholas Oliveira commented
Hi,
I think that you use the code bellow, will help you:
import json
import decimal
data = json.loads(data, parse_float=decimal.Decimal) # default is float(num_str)
Thank you.