2013-06-06 13 views
25

Ho un oggetto python che include alcuni decimali. Ciò sta causando l'interruzione di json.dumps().La serializzazione da Python a JSON non riesce su Decimale

Ho ottenuto la seguente soluzione da SO (ad esempio Python JSON serialize a Decimal object) ma la soluzione di riepilogo ancora non funziona. Sito Web Python - ha la stessa risposta esatta.

Qualche suggerimento su come farlo funzionare?

Grazie. Di seguito è il mio codice. Sembra che i dump() non entrino nemmeno nell'encoder specializzato.

[email protected]:~/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 
[email protected]:~/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 
[email protected]:~/python> 
+0

Sia la seconda risposta sulla pagina collegata e [la documentazione Python reale] (http: // docs.python.org/2/library/json.html#json.JSONEncoder) fornisce la risposta corretta, che è quella di sovrascrivere 'default'. Dovrebbe essere ovvio che non si dovrebbe sovrascrivere '_iterencode', poiché la sottolineatura principale implica che si tratta di un metodo solo interno. –

+0

json non sa come gestire 'Decimal', quindi si dovrebbe estendere il codificatore JSON per le strutture dati Pythonhttp: //docs.python.org/2/library/json.html#py-to-json-table – oleg

risposta

60

Non è (non più) consigliato di creare una sottoclasse; le json.dump() e json.dumps() funzioni prendono una funzione default:

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}' 

Il codice che hai trovato lavorato solo su Python 2.6 e sovrascrive un metodo privato che non viene più chiamato nelle versioni successive.

+1

non dovrebbe la tua funzione 'decimal_default 'restituisce' float (str (obj)) 'o qualcosa del genere? – oleg

+0

@oleg: l'esempio di codice OP utilizzato str. Puoi restituire tutto ciò che ti piace fintanto che è serializzabile in JSON. –

+0

Perché non creare una sottoclasse? Non è molto meno DRY passare un argomento su ogni chiamata in ogni file (e/o incline a provare e usarlo ovunque ci si aspetti che un decimale possa essere inserito nell'input)? –

14

Non riesco a credere che nessuno qui abbia parlato dell'uso di simplejson, che supporta la deserializzazione del decimale.

import simplejson 
from decimal import Decimal 

simplejson.dumps({"salary": Decimal("5000000.00")}) 
'{"salary": 5000000.00}' 

simplejson.dumps({"salary": Decimal("1.1")+Decimal("2.2")-Decimal("3.3")}) 
'{"salary": 0.0}' 
+0

Grazie per l'introduzione a 'simplejson' – Dinesh

+1

Sembra semplice ma ha i giorni ma almeno come parte predefinita di Django https://docs.djangoproject.com/en/1.8/internals/deprecation/#deprecation -removed-in-1-7 – wasabigeek

+1

Ci sono degli svantaggi usando simplejson come questo? Altrimenti perché tante risposte vanno nel modo più duro? – benjaminz

Problemi correlati