我试图创建一个类实例的JSON字符串表示,有困难。假设这个类是这样构建的:
class testclass:
value1 = "a"
value2 = "b"
对json的调用。转储是这样的:
t = testclass()
json.dumps(t)
它失败了,告诉我测试类不是JSON序列化的。
TypeError: <__main__.testclass object at 0x000000000227A400> is not JSON serializable
我也尝试过使用pickle模块:
t = testclass()
print(pickle.dumps(t, pickle.HIGHEST_PROTOCOL))
它提供类实例的信息,而不是类实例的序列化内容。
b'\x80\x03c__main__\ntestclass\nq\x00)\x81q\x01}q\x02b.'
我做错了什么?
有一种方法非常适合我,你可以试试:
Json.dumps()可以接受一个可选参数default,您可以在其中为未知类型指定一个自定义序列化器函数,在我的例子中是这样的
def serialize(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, date):
serial = obj.isoformat()
return serial
if isinstance(obj, time):
serial = obj.isoformat()
return serial
return obj.__dict__
前两个if用于日期和时间序列化
然后有一个obj。为任何其他对象返回__dict__。
最终决定是这样的:
json.dumps(myObj, default=serialize)
当你在序列化一个集合,并且你不想为每个对象显式地调用__dict__时,它特别好。这里是自动完成的。
到目前为止对我来说很好,期待你的想法。
这里有一些关于如何开始做这件事的很好的答案。但有一些事情要记住:
如果实例嵌套在大型数据结构中怎么办?
如果还想要类名呢?
如果要反序列化实例该怎么办?
如果你使用__slots__而不是__dict__呢?
如果你只是不想自己动手呢?
json-tricks是一个库(我创建的,其他人贡献的),它已经能够做到这一点很长时间了。例如:
class MyTestCls:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
cls_instance = MyTestCls(s='ub', dct={'7': 7})
json = dumps(cls_instance, indent=4)
instance = loads(json)
您将得到您的实例。这里的json是这样的:
{
"__instance_type__": [
"json_tricks.test_class",
"MyTestCls"
],
"attributes": {
"s": "ub",
"dct": {
"7": 7
}
}
}
如果你喜欢自己做解决方案,你可以查看json-tricks的源代码,以免忘记一些特殊情况(如__slots__)。
它也可以处理其他类型,比如numpy数组,datetimes,复数;它还允许注释。
基本的问题是JSON编码器JSON .dumps()默认情况下只知道如何序列化有限的对象类型集,所有的内置类型。名单在这里:https://docs.python.org/3.3/library/json.html#encoders-and-decoders
一个好的解决方案是让您的类继承自JSONEncoder,然后实现JSONEncoder.default()函数,并使该函数为您的类发出正确的JSON。
一个简单的解决方案是在该实例的.__dict__成员上调用json.dumps()。这是一个标准的Python字典,如果你的类很简单,它将是JSON序列化的。
class Foo(object):
def __init__(self):
self.x = 1
self.y = 2
foo = Foo()
s = json.dumps(foo) # raises TypeError with "is not JSON serializable"
s = json.dumps(foo.__dict__) # s set to: {"x":1, "y":2}
上述方法在这篇博文中进行了讨论:
使用_dict_将任意Python对象序列化为JSON
当然,Python提供了一个内置函数,为您访问.__dict__,称为vars()。
所以上面的例子也可以这样做:
s = json.dumps(vars(foo)) # s set to: {"x":1, "y":2}
你可以使用Jsonic将几乎任何东西序列化为JSON:
https://github.com/OrrBin/Jsonic
例子:
class TestClass:
def __init__(self):
self.x = 1
self.y = 2
instance = TestClass()
s = serialize(instance): # instance s set to: {"x":1, "y":2}
d = deserialize(s) # d is a new class instance of TestClass
Jsonic有一些不错的特性,比如声明类属性为瞬态的和类型安全的反序列化。
(晚了几年才有答案,但我认为这可能会对其他人有所帮助)
我只会:
data=json.dumps(myobject.__dict__)
这不是完整的答案,如果你有某种复杂的对象类,你肯定不会得到所有的东西。然而,我在一些简单的对象中使用这种方法。
它工作得非常好的一个是您从OptionParser模块中获得的“options”类。
下面是它和JSON请求本身。
def executeJson(self, url, options):
data=json.dumps(options.__dict__)
if options.verbose:
print data
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
return requests.post(url, data, headers=headers)