Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python to JSON Serialization fails on Decimal [duplicate]

I have a python object which includes some decimals. This is causing the json.dumps() to break.

I got the following solution from SO (e.g. Python JSON serialize a Decimal object) but the recoomended solution still does not work. Python website - has the exact same answer.

Any suggestions how to make this work?

Thanks. Below is my code. It looks like the dumps() doesn't even go into the specialized encoder.

clayton@mserver:~/python> cat test1.py import json, decimal  class DecimalEncoder(json.JSONEncoder):         def _iterencode(self, o, markers=None):                 print "here we go o is a == ", type(o)                 if isinstance(o, decimal.Decimal):                         print "woohoo! got a decimal"                         return (str(o) for o in [o])                 return super(DecimalEncoder, self)._iterencode(o, markers)  z = json.dumps( {'x': decimal.Decimal('5.5')}, cls=DecimalEncoder ) print z clayton@mserver:~/python> python test1.py Traceback (most recent call last):   File "test1.py", line 11, in <module>     z = json.dumps( {'x': decimal.Decimal('5.5')}, cls=DecimalEncoder )   File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/__init__.py", line 238, in dumps     **kw).encode(obj)   File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 201, in encode     chunks = self.iterencode(o, _one_shot=True)   File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 264, in iterencode     return _iterencode(o, 0)   File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 178, in default     raise TypeError(repr(o) + " is not JSON serializable") TypeError: Decimal('5.5') is not JSON serializable clayton@mserver:~/python> 
like image 261
Dinesh Avatar asked Jun 06 '13 08:06

Dinesh


1 Answers

It is not (no longer) recommended you create a subclass; the json.dump() and json.dumps() functions take a default function:

def decimal_default(obj):     if isinstance(obj, decimal.Decimal):         return float(obj)     raise TypeError  json.dumps({'x': decimal.Decimal('5.5')}, default=decimal_default) 

Demo:

>>> def decimal_default(obj): ...     if isinstance(obj, decimal.Decimal): ...         return float(obj) ...     raise TypeError ...  >>> json.dumps({'x': decimal.Decimal('5.5')}, default=decimal_default) '{"x": 5.5}' 

The code you found only worked on Python 2.6 and overrides a private method that is no longer called in later versions.

like image 167
Martijn Pieters Avatar answered Sep 17 '22 21:09

Martijn Pieters