Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带有simplejson后端的jsonpickle将十进制序列化为null_Python_Python 3.x_Simplejson_Jsonpickle - Fatal编程技术网

Python 带有simplejson后端的jsonpickle将十进制序列化为null

Python 带有simplejson后端的jsonpickle将十进制序列化为null,python,python-3.x,simplejson,jsonpickle,Python,Python 3.x,Simplejson,Jsonpickle,我试图在Python3.7中使用jsonpickle将对象树序列化为json。但是,所有的Decimals都被序列化为null。我使用simplejson作为后端,因此应该能够序列化小数 如何将(复杂的)对象树序列化为json,包括小数 示例代码(需要安装simplejson和jsonpickle): 预期的序列化json应该是{“amount”:1.0},由于舍入错误,我不想使用float import jsonpickle from decimal import Decimal jsonp

我试图在Python3.7中使用jsonpickle将对象树序列化为json。但是,所有的
Decimal
s都被序列化为
null
。我使用simplejson作为后端,因此应该能够序列化小数

如何将(复杂的)对象树序列化为json,包括小数

示例代码(需要安装simplejson和jsonpickle): 预期的序列化json应该是
{“amount”:1.0}
,由于舍入错误,我不想使用
float

import jsonpickle
from decimal import Decimal

jsonpickle.set_preferred_backend('simplejson')
jsonpickle.set_encoder_options('simplejson', use_decimal=True)

class MyClass():
    def __init__(self, amount):
        self.amount = amount

    def to_json(self):
        return jsonpickle.dumps(self, unpicklable=False)

if __name__ == '__main__':
    obj = MyClass(Decimal('1.0'))
    print(obj.to_json())  # prints '{"amount": null}'

PS我不在乎使用jsonpickle。因此,将复杂对象树序列化为json(包括十进制字段)的jsonpickle替代方案也很受欢迎。

您需要注册一个处理程序来处理十进制类

import jsonpickle
from decimal import Decimal

jsonpickle.set_preferred_backend('simplejson')
jsonpickle.set_encoder_options('simplejson', use_decimal=True)

class DecimalHandler(jsonpickle.handlers.BaseHandler):

    def flatten(self, obj, data):

        return obj.__str__() #Convert to json friendly format

jsonpickle.handlers.registry.register(Decimal, DecimalHandler)

class MyClass():
    def __init__(self, amount):
        self.amount = amount

    def to_json(self):
        return jsonpickle.dumps(self, unpicklable=False)

if __name__ == '__main__':
    obj = MyClass(Decimal('1.0'))
    print(obj.to_json())

更新答案:jsonpickle的主分支现在有一个use_decimal模式,允许您在不使用任何自定义处理程序的情况下实现此结果

import decimal
import unittest

import jsonpickle


class Example(object):
    """Example class holding a Decimal"""

    def __init__(self, amount):
        self.amount = decimal.Decimal(amount)


class UseDecimalTestCase(unittest.TestCase):
    """Demonstrate the new use_decimal mode"""

    def test_use_decimal(self):

        obj = Example(0.5)

        # Configure simplejson to use decimals.
        jsonpickle.set_encoder_options('simplejson', use_decimal=True, sort_keys=True)
        jsonpickle.set_preferred_backend('simplejson')

        as_json = jsonpickle.dumps(obj, unpicklable=False, use_decimal=True)
        print(as_json)
        # {"amount": 0.5}

        # Configure simplejson to get back Decimal when restoring from json.
        jsonpickle.set_decoder_options('simplejson', use_decimal=True)
        obj_clone = jsonpickle.loads(as_json)

        # NOTE: we get back a dict, not an Example instance.
        self.assertTrue(isinstance(obj_clone, dict))
        # But, the Decimal *is* preserved
        self.assertTrue(isinstance(obj_clone['amount'], decimal.Decimal))
        self.assertEqual(obj.amount, obj_clone['amount'])

        # Side-effect of simplejson decimal mode:
        # floats become Decimal when round-tripping
        obj.amount = 0.5  # float
        as_json = jsonpickle.dumps(obj, unpicklable=False)
        obj_clone = jsonpickle.loads(as_json)
        self.assertTrue(isinstance(obj_clone['amount'], decimal.Decimal))


if __name__ == '__main__':
    unittest.main()

相关问题:

对于较旧的jsonpickle版本:

这可以通过允许simplejson进行编码的自定义传递处理程序来完成。您必须配置编码器和解码器选项,以便返回小数。如果您不关心往返,那么用例就更简单了

import decimal
import unittest

import jsonpickle
from jsonpickle.handlers import BaseHandler


class SimpleDecimalHandler(BaseHandler):
    """Simple pass-through handler so that simplejson can do the encoding"""

    def flatten(self, obj, data):
        return obj

    def restore(self, obj):
        return obj



class Example(object):
    """Example class holding a Decimal"""

    def __init__(self, amount):
        self.amount = decimal.Decimal(amount)



class DecimalTestCase(unittest.TestCase):
    """Test Decimal json serialization"""

    def test_custom_handler(self):

        obj = Example(0.5)

        # Enable the simplejson Decimal handler -- slightly simpler than jsonpickle's
        # default handler which does the right thing already.
        # If you don't care about the json representation then you don't
        # need to do anything -- jsonpickle preserves decimal by default
        # when using its default dumps() options.
        #
        # We use this decimal handler so that simplejson does the encoding
        # rather than jsonpickle.  Thus, we have to configure simplejson too,
        # which is not needed otherwise when using jsonpickle's defaults.

        jsonpickle.set_encoder_options('simplejson', use_decimal=True, sort_keys=True)
        jsonpickle.set_decoder_options('simplejson', use_decimal=True)
        jsonpickle.set_preferred_backend('simplejson')

        SimpleDecimalHandler.handles(decimal.Decimal)
        as_json = jsonpickle.dumps(obj)

        print(as_json)
        # {"amount": 0.5, "py/object": "__main__.Example"}

        # NOTE: this comes back as an Example instance
        clone = jsonpickle.loads(as_json)

        self.assertTrue(isinstance(clone, Example))
        self.assertTrue(isinstance(clone.amount, decimal.Decimal))
        self.assertEqual(obj.amount, clone.amount)


        # We can simplify the JSON representation a little further
        # by using unpickleable=False, but we lose the Example class.
        as_json = jsonpickle.dumps(obj, unpicklable=False)

        # Upside: this prints {"amount": 0.5}
        # Downside: this object cannot be reconstructed back into an
        # instance of the Example class.
        print(as_json)

        # NOTE: we get back a dict, not an Example instance.
        obj_clone = jsonpickle.loads(as_json)
        self.assertTrue(isinstance(obj_clone, dict))

        # But, the Decimal *is* preserved
        self.assertTrue(isinstance(obj_clone['amount'], decimal.Decimal))
        self.assertEqual(obj.amount, obj_clone['amount'])


if __name__ == '__main__':
    unittest.main()

这实际上打印的是
{“amount”:“1.0”}
,我希望它是
{“amount”:1.0}
(小数点周围没有引号)。@JessedeWit您可以将obj.\uu str_uuuuuuuuuuuuuu()转换为带浮点数的浮点数(obj.\uu str_uuuuuuuuuuuuuuu()),我担心浮点数会产生舍入错误。这就是我尝试使用simplejson的原因。simplejson能够序列化小数,但显然不能与jsonpickle一起使用。