10

I'm pulling a sum from a DB which is a decimal value. I'm trying to use that value in a JSON result

json.dumps( { 'sum': amount } ) #where amount is my Decimal

Django can't serialize the Decimal. I can convert it to a string, but I'd like a numeric type within the JSON. If I try and convert it to a float I end up with more than 2 decimal places.

What needs to happen, if possible, to get a result like the following?

{ 'sum': 500.50 }
Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
Justin
  • 4,434
  • 4
  • 28
  • 37
  • I don't know much about django, but if you need two decimal places always and it's not possible to do exactly what you want you could multiply by 100 and work with it as an integer. – cambraca Oct 26 '10 at 00:31
  • 1
    JSON is only defined to have double-precision floats for numbers. What does it buy you to keep your numbers as Decimals? – Gabe Oct 26 '10 at 00:41
  • I don't need my numbers to be Decimal, they will never be that large. That's just what I get back from the DB as they are monetary values. I wasn't thrilled about using the int * 100 and floats give me more than two decimal places. I was just hoping there would be a more elegant solution... – Justin Oct 26 '10 at 03:48

4 Answers4

12

What you can do is extend the JSONDecoder class to provide a custom serializer for the Decimal type, similar to the example in this document: http://docs.python.org/py3k/library/json.html

>>> import json
>>> class DecimalEncoder(json.JSONEncoder):
...     def default(self, obj):
...         if isinstance(obj, Decimal):
...             return "%.2f" % obj
...         return json.JSONEncoder.default(self, obj)
...

That's a nonworking example of how to do it, hopefully a good starting point for you.

Jerub
  • 41,746
  • 15
  • 73
  • 90
  • Thanks, I like this solution the best so far :) – Justin Oct 26 '10 at 03:53
  • 10
    Actually Django provides a built-in class for exactly this - `django.core.serializers.json.DjangoJSONEncoder` - which you can use directly by doing `simplejson.dumps(mydict, class=DjangoJSONEncoder)`. It also deals with datetimes. – Daniel Roseman Oct 26 '10 at 08:08
  • 4
    @Daniel Thanks. 'class=DjangoJSONEncoder' needed to be 'cls=DjangoJSONEncoder'. This does work, but it gives me a string value :( – Justin Oct 26 '10 at 14:58
  • hehe this gives me just a string value the same as just doing 'str(amount)' in the json.dumps calls... I've decided to just leave it as a string and handle it on the client.. – Justin Oct 28 '10 at 05:16
  • You can make it whatever you want, just change the `return "%.2f" % obj` line. – Jerub Oct 28 '10 at 06:41
0

From this link : http://code.google.com/p/simplejson/issues/detail?id=34.

i can tell you tree think :

you can find more detail in the first link.

mouad
  • 67,571
  • 18
  • 114
  • 106
0

Decimal can be cast to a float which javascript knows how to deal with

json.dumps( { 'sum': float(amount) } )
mossplix
  • 3,783
  • 2
  • 26
  • 31
  • In my question I noted that I didn't want to pass down a float due to them having a large number of decimal places. – Justin Oct 28 '10 at 05:14
-1

There's no such thing as a Decimal type in Javascript, and also among the standard types in python. It is a database-spcific type and not part of JSON. Take Float or do an integer arithmetic.

knitti
  • 6,817
  • 31
  • 42
  • Yes, I know there is no matching type in JavaScript, my values will never be that large. I simply want them to come down in a regular monetary format "5.95", but not in string format. – Justin Oct 26 '10 at 03:45
  • JSON standard is independent from JS. Also it defines numbers as sequence of digits with optional - and . not discussing the memory representation after parsing the number. Decimal is also standard in Python from 2.4, you have to import it explicitly thou (from decimal import Decimal). It's built-in nevertheless. – jaboja Jun 07 '18 at 09:40