6

i have this model using Flask-SQLAlchemy:

class Menu(Document, db.Model):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(80), unique=True, index=True)
    price = db.Column(db.Numeric)

and i can create api using Flask-Restless for this model. The problem is when i HTTP GET from the api url:

  File "/usr/lib/python2.6/json/encoder.py", line 344, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Decimal('10000.0000000000') is not JSON serializable

The problem is obvious the JSON encoder cannot encode Decimal value which is mapped to price (Numeric column type). Is there any workaound to enable Flask-Restless using custom JSON encoder?

desdulianto
  • 83
  • 2
  • 6

2 Answers2

5

Here is what I did:

import simplejson as json

def postprocessor(data):
    json.dumps(data, use_decimal=True)
    return data

manager.create_api(Menu, methods=['GET', 'POST', 'PATCH'], allow_patch_many=True, postprocessors={
'PATCH_MANY': [postprocessor],
'GET_MANY': [postprocessor],
'POST': [postprocessor]
})

So the idea is to use Flask-Restless' postprocessor to encode the data with simplejson instead of json since simplejson supports the Decimal() type by specifying use_decimal=True.

Edit: Actually it seems like installing simplejson might be sufficient. No change needed in your code.

Phonolog
  • 6,321
  • 3
  • 36
  • 64
mickael
  • 315
  • 4
  • 9
4

As indicated in mickael's answer, installing simpejson was sufficient. Also correct syntax for postprocessor is the following:

#first argument must be named as 'result', not 'data'
def postprocessor(result):
    json.dumps(result, use_decimal=True)
    #return data - postprocessors/preprocessors should not return values!
synergetic
  • 7,756
  • 8
  • 65
  • 106