我在让Python的jsonpickle 0.4.0“递归”到包含自定义对象的自定义对象时遇到了麻烦。下面是显示我的问题的示例代码。
import jsonpickle
import jsonpickle.handlers
class Ball(object):
def __init__(self, color):
self.color = color
class Box(object):
def __init__(self, *args):
self.contents = args
class BallHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
data['color'] = obj.color
return data
class BoxHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
data['contents'] = obj.contents
return data
jsonpickle.handlers.registry.register(Ball, BallHandler)
jsonpickle.handlers.registry.register(Box, BoxHandler)
# works OK -- correctly prints: {"color": "white"}
white_ball = Ball('white')
print jsonpickle.encode(white_ball, unpicklable=False)
# works OK -- correctly prints: [{"color": "white"}, {"color": "green"}]
green_ball = Ball('green')
balls = [white_ball, green_ball]
print jsonpickle.encode(balls, unpicklable=False)
# works OK -- correctly prints: {"contents": [1, 2, 3, 4]}
box_1 = Box(1, 2, 3, 4)
print jsonpickle.encode(box_1, unpicklable=False)
# dies with "Ball object is not JSON serializable"
box_2 = Box(white_ball, green_ball)
print jsonpickle.encode(box_2, unpicklable=False)球有“颜色”,盒子有“内容”。如果我有一个原生的Ball数组,那么jsonpickle就可以工作。如果我有一个原生int的盒子,那么jsonpickle就可以工作了。
但如果我有一盒球,jsonpickle用"Ball object is not JSON serializable"炸弹。
从堆栈跟踪中,我预感到编码器将离开jsonpickle,转而使用其他JSON库……显然不知道我已经注册了BallHandler。
我该怎么解决这个问题呢?
顺便说一下,我的示例没有明确使用Django的任何部分,但我需要在Django应用程序中使用它。
提前感谢您的任何意见!
发布于 2017-06-21 10:39:10
我认为您可以回调到酸洗上下文以继续酸洗。
class BoxHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
return [self.context.flatten(x,reset=False) for x in obj.contents]这似乎类似于pickler.py:44中内置的_list_recurse()函数处理这种情况的方式,因为flatten()只是调用self._flatten (在可选地重置状态变量之后)。
def _list_recurse(self, obj): return [self._flatten(v) for v in obj]
我现在正在对此进行测试,_depth似乎如预期的那样得到了维护。
发布于 2013-01-15 09:08:14
首先,为什么首先要创建自定义处理程序?您正在尝试做与默认处理程序已经做过的完全相同的事情。删除这两行register代码,并使用和不使用unpicklable=False对所有这些对象调用encode,您将获得相同的结果-除了它将完全按照您希望的方式处理装满球的盒子,而不是失败。
如果您通读教程、API、测试用例和示例,就会发现它们从未创建自定义处理程序来模拟这样的集合。(例如,看看测试套件(samples.py和document_test.py)中的Node/Document/Section类。)所以,我认为你正在尝试做一些你不希望做的事情,也不打算做的事情。
但是,让我们看看你的实际问题:为什么它不工作?
好吧,这个很简单。你做错了。根据BaseHandler.flatten的文档,您应该:
将obj扁平化为json友好的形式。
因此,考虑到以下情况:
class BoxHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
data['contents'] = obj.contents
return data您有效地保证了obj.contents是JSON友好的形式。但它不是;它是Ball对象的list。
那么,正确的答案是什么呢?嗯,你可以像你被展平一样展平内容中的每个元素。您可能认为有一些简单的方法可以做到这一点,但老实说,我在API、文档、示例或单元测试中看不到任何东西,所以我猜没有,所以您必须手动完成。大概是这样的(未经测试):
class BoxHandler(jsonpickle.handlers.BaseHandler):
def flatten(self, obj, data):
p = jsonpickle.Pickler()
data['contents'] = [p.flatten(elem) for elem in obj.contents]
return data但是…由于您得到的不是用来筛选您的相同Pickler --我看不出有任何方法可以--这很可能会违反encode的maxdepth和unpicklable参数。
因此,也许没有正确的方法来做到这一点。
发布于 2013-01-15 09:21:25
如果jsonpickle与向json添加自定义对象处理有关,那么它应该集成到后者中,而不是试图为其“预处理”内容。要求用户自己处理这件事的现状是,as abarnert said将责任推到了另一个人的头上。
如果我是你,我会自己解决这个问题,或者让我的对象像JSON一样友好--比如让它们看起来像原生Python数据结构(JSON是原生Python数据结构的替代表示)。一种更简单的方法是避免这样的构造,这当然是一种杂乱无章的东西。
https://stackoverflow.com/questions/14329531
复制相似问题