2013-06-06 15 views
25

私はいくつかの小数を含むpythonオブジェクトを持っています。これにより、json.dumps()が中断しています。PythonとJSONのシリアル化が小数点で失敗する

私はSOから次のような解決策を得ましたが(例:Python JSON serialize a Decimal object)、 の解決策はまだ機能しません。 Pythonのウェブサイト - まったく同じ答えを持っています。

どのようにこの作品を作るための提案?

ありがとうございました。以下は私のコードです。ダンプ()は特殊なエンコーダにも入っていないようです。

[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

どちらのリンクページの2番目の答えと[実際のPythonのドキュメント](HTTP:10進数と日付フィールドのための偉大なクラスがあります// docs.python.org/2/library/json.html#json.JSONEncoder)は正しい答えを返します。これは 'default'を上書きすることです。先頭のアンダースコアはそれが内部のみのメソッドであることを意味するので、 '_iterencode'をオーバーライドすべきではないことは明らかです。 –

+0

jsonは 'Decimal'を扱う方法を知らないので、Pythonデータ構造のJSONエンコーダを拡張する必要があります.http://docs.python.org/2/library/json.html#py-to-json-table – oleg

答えて

60

サブクラスを作成することは推奨されていません。

def decimal_default(obj): 
    if isinstance(obj, decimal.Decimal): 
     return float(obj) 
    raise TypeError 

json.dumps({'x': decimal.Decimal('5.5')}, default=decimal_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) 
'{"x": 5.5}' 

あなただけのPython 2.6に勤務し、もはやそれ以降のバージョンで呼ばれているプラ​​イベートメソッドをオーバーライドしたコードjson.dump()json.dumps()機能がdefault機能を取ります。

+1

あなたの 'decimal_default '関数は' float(str(obj)) 'かこれを返すでしょうか? – oleg

+0

@oleg:strを使用したOPコードサンプル。 JSONシリアライズ可能な限り、好きなものを返すことができます。 –

+0

サブクラスを作ってみませんか?すべてのファイルのすべての呼び出しで引数を渡すのがDRYより少ないのでしょうか(そして、入力dictにDecimalがあると思われる場所であればどこでも試してみてください)。 –

14

ここでは、Decimalのデシリアライズをサポートするsimplejsonの使用について、ここでは誰も話していないとは思いません。

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

'simplejson'の紹介に感謝します – Dinesh

+1

Djangoのデフォルト部分としてはsimplejsonに番号が付けられているようですhttps://docs.djangoproject.com/en/1.8/internals/deprecation/#deprecation -removed-in-1-7 – wasabigeek

+1

このようなsimplejsonを使用している欠点はありますか?それ以外の理由でそれほど多くの答えが難しいのはなぜですか? – benjaminz

関連する問題