10

I have a query set which contains Decimal objects. I want to pass this data to a json dump along the lines:

ql = Product.objects.values_list('length', 'width').get(id=product_id)
data = simplejson.dumps(ql)

TypeError: Decimal('62.20') is not JSON serializable

How should I pass these values to json. Of course I could cast the values to string - but I'm guessing this is not a good solution.

Any help much appreciated.

Darwin Tech
  • 18,449
  • 38
  • 112
  • 187

2 Answers2

24

Django already includes an encoder than can deal with decimals, as well as datetimes: django.core.serializers.json.DjangoJSONEncoder. Just pass that as the cls parameter:

data = simplejson.dumps(ql, cls=DjangoJSONEncoder)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I have a problem here. I setted the context to 2 decimals points, but it keeps dumping the whole 8 or 10 decimals points. What I'm missing here? – Cheluis Dec 02 '12 at 17:18
  • 2
    Note you will get a `TypeError` error if you are serializing a query set when using `.values` or `.values_list` which returns a `ValuesQuerySet` - force into list for it to work so using above as example it would be: `data = simplejson.dumps(list(ql), cls=DjangoJSONEncoder)` – Daniel Sokolowski Sep 06 '13 at 19:40
1

Here's an answer I found on this question: Python JSON serialize a Decimal object

How about subclassing json.JSONEncoder?

class DecimalEncoder(simplejson.JSONEncoder):
    def _iterencode(self, o, markers=None):
        if isinstance(o, decimal.Decimal):
            # wanted a simple yield str(o) in the next line,
            # but that would mean a yield on the line with super(...),
            # which wouldn't work (see my comment below), so...
            return (str(o) for o in [o])
        return super(DecimalEncoder, self)._iterencode(o, markers)

In your case, you would use it like this:

data = simplejson.dumps(ql, cls=DecimalEncoder)
Community
  • 1
  • 1
Amit
  • 981
  • 2
  • 9
  • 16