Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django DecimalField is rendered as string in json #582

Closed
yprez opened this issue Jan 15, 2013 · 15 comments
Closed

Django DecimalField is rendered as string in json #582

yprez opened this issue Jan 15, 2013 · 15 comments

Comments

@yprez
Copy link
Contributor

yprez commented Jan 15, 2013

This was introduced in 2.1.16

@tomchristie
Copy link
Member

What makes you think this is introduced in 2.1.16?
As far as I'm aware Decimals have always (intentionally) rendered as strings in json.

JSON has no decimal representation, so it's not obvious what sensible behavior is. See #508.

If you treat them as floats you get anomalies due to binary floating point not being able to precisely represent decimal numbers.

eg. try this in a python console...

>>> 0.1
0.10000000000000001

@tomchristie
Copy link
Member

That's not to say that we couldn't consider instead rendering them using a correct decimal notation in json, but it's not obvious if that's a sensible thing to do given that clients will then decode that into binary floating point.

@yprez
Copy link
Contributor Author

yprez commented Jan 15, 2013

Yes... weird
After looking at the encoders file, it doesn't make much sense.
However, I'm absolutely sure that decimals were rendered as floats in 2.1.15

Not sure what fixed it, but it should probably be in the changelog in case someone relies on it...

@yprez
Copy link
Contributor Author

yprez commented Jan 15, 2013

with 2.1.15:

>>> from decimal import Decimal
>>> from rest_framework import renderers
>>> 
>>> obj = {'foo': ['bar', 'baz'], 'float': 1.1, 'decimal': Decimal(1.1)}
>>> 
>>> renderers.JSONRenderer().render(obj, 'application/json')
'{"float": 1.1, "decimal": 1.100000000000000088817841970012523233890533447265625, "foo": ["bar", "baz"]}'`

with 2.1.16:

>>> renderers.JSONRenderer().render(obj, 'application/json')
'{"float": 1.1, "decimal": "1.100000000000000088817841970012523233890533447265625", "foo": ["bar", "baz"]}'

@tomchristie
Copy link
Member

Urg? Don't know how the behavior's changed, but in either case 2.1.15 is broken, and 2.1.16 is even more broken. :-/

(If it's going to be a string repr it should at least be a decimal string repr)

Note that if you want to put together a failing test case for DecimalFields, this module is intended for basic field tests: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/tests/fields.py

@yprez
Copy link
Contributor Author

yprez commented Jan 15, 2013

My mistake... I should've created decimals from strings not floats...

>>> str(Decimal(1.1))
'1.100000000000000088817841970012523233890533447265625'

The types are still the same though...

>>> obj = {'foo': ['bar', 'baz'], 'float': 1.1, 'decimal': Decimal('1.1')}
>>> 
>>> renderers.JSONRenderer().render(obj, 'application/json')
'{"float": 1.1, "decimal": 1.1, "foo": ["bar", "baz"]}'

@yprez
Copy link
Contributor Author

yprez commented Jan 15, 2013

I can't replicate it in the DRF env for some reason... this is getting really weird.

@yprez
Copy link
Contributor Author

yprez commented Jan 15, 2013

Ok... found it... a061e3d
It's the switch from simplejson to the builtin that caused this for me...

@yprez
Copy link
Contributor Author

yprez commented Jan 16, 2013

@tomchristie, So what should we do with the decimals? Leave them as strings?

Before 2.1.16, users who had simplejson installed had them rendered as floats, and without it as strings...
Maybe leave it as is and add a note in the changelog?

@minddust
Copy link
Contributor

+1 for accuracy and strings

@yprez
Copy link
Contributor Author

yprez commented Jan 16, 2013

Awesome, thanks.

@StErMi
Copy link

StErMi commented Mar 25, 2016

Django==1.9.4
djangorestframework==3.3.2

Is this bug still opened? Because I was just using DecimalField and in my JSON it's rappresented as a string.

UPDATE: my bad, din't see the coerce_to_string parameter. Sorry guys!

@SalahAdDin
Copy link

Which parameter?

@ChristopherBrix
Copy link

@ghost
Copy link

ghost commented Apr 20, 2016

The coerce_to_string param is available to 2.3.14? i getting the error got an unexpected keyword argument 'decimal_places' :/ Any tips on how to make it work on 2.3?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants