cenobites / flask-jsonrpc

Basic JSON-RPC implementation for your Flask-powered sites

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Decimal cannot be json.dumps()

caimaoy opened this issue · comments

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)

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.