decorator approach to JSON serializing?
我使用JSON将数据从python发送到r(注意:我比python更熟悉r)。对于原语,json模块工作得很好。对于许多其他的python对象(例如numpy数组),您必须定义一个自定义编码器,就像在这个堆栈溢出答案中一样。但是,这需要您将编码器作为一个参数传递给json.dumps,这对于我的情况来说并不是很好。我知道还有其他一些包,比如json_tricks,它们具有更高级的JSON序列化功能,但是由于我无法控制用户拥有的Python分发,所以我不想依赖任何非默认模块将对象序列化到JSON。
我想知道是否有一种方法可以使用contextlibdecorators来定义序列化JSON对象的其他方法。理想情况下,我正在寻找一种方法,允许用户重载一些标准函数standard_wrapper,我提供这些函数来为自己的类(或从模块加载的类型)添加新方法,而不需要用户修改standard_wrapper。下面是一些伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import json
def standard_wrapper(o):
return o
obj = [44,64,13,4,79,2,454,89,0]
json.dumps(obj)
json.dumps(standard_wrapper(obj))
import numpy as np
objnp = np.sort(obj)
json.dumps(objnp) # FAILS
@some_decorator_to_overload_standard_wrapper
# some code
json.dumps(standard_wrapper(objnp)) # HOPEFULLY WORKS |
这本质上是按类型进行的函数重载——我在Python中看到过用参数进行重载的示例,但我不知道如何按类型进行重载。
编辑我把装饰师和contextlib混在一起(我只见过用过装饰师)。
- 我觉得很神秘,你为什么想用contextlib来解决这个问题?你有什么想法?无论如何,使用常规编码器使对象JSON可序列化的问题的答案可能会有所帮助。
- 我不想为自定义类创建编码器,我想要一个框架,允许用户定义自己的方法来序列化一个不会与现有方法冲突的对象,并且不需要为json.dumps指定自定义cls参数。我想我在寻找一个与R中的S3方法等效的Python。
- 我听上去不像你读我对相关问题的回答。它演示了如何钩住JSON编码方案并执行您想要的任何操作。代码使用pickle作为示例,因为它可以序列化许多常见的Python类型,而无需做任何进一步的工作。它是一个可扩展的系统,所以许多作者添加了方法来支持它到他们的类中。我认为让你自己的"框架"使用用户提供的"方法"来做事情是相当简单的,但是这样做需要某种方法来将它们与使用cls的适当对象相关联,这是一个显而易见的选择。
- @马蒂诺,我读过你的链接,但它要求更换默认编码器。只有当我提前知道我需要支持的每种可能的数据类型时,这才有效。我正在寻找一种解决方案,允许用户扩展编码器(默认编码器或我提供的编码器),以支持其他数据类型,而无需完全覆盖编码器。
- 抱歉,我仍然不认为您得到了它,因为它不一定要求您提前知道每种可能的数据类型。只有当股票编码器遇到一些它还不知道如何处理的东西时,才会调用补丁。这基本上给了你一个"钩子",当它发生时,你需要做任何你想做的事情,这可能包括看看你的用户提供了什么,看看是否有什么东西可以处理问题中的对象类型。我会告诉你怎么做,但我没有安装numpy,也不想这样做。
- 对于按类型重载函数,您不了解如何执行它?不检查传递的参数的值,只检查其类型(使用isinstance())。
使用functools模块中的singledispatch可以很容易地按类型重载函数,如此答案所示。然而,一个可能适合我需要的简单的解决方案是创建一个函数字典,其中键对应于对象类型。
1 2 3 4 5 6 7 8 9 10 11
| import numpy
func_dict = {}
a = [2,5,2,9,75,8,36,2,8]
an = numpy.sort(a)
func_dict[type(an)] = lambda x: x.tolist()
func_dict[type(a)] = lambda x: x
import json
json.dumps(func_dict[type(a)](a))
json.dumps(func_dict[type(an)](an)) |
通过向字典中添加另一个函数来增加对另一类型的支持。
- 这更简单?您的用户的解决方案是,他们不需要知道他们创建的类型是什么,但他们需要知道要转换为什么类型才能序列化。在我看来,了解适当的可序列化类型比您创建的数据结构类型更难发现。更简单的答案是本文中说明的第一个选项:hynek.me/articles/serialization singledispatch方法,也是在本文中,回答您的原始问题,使用修饰符"通过类型重载函数"即动态调度。