我试图创建一个类实例的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.'
我做错了什么?
这可以用pydantic轻松处理,因为它已经内置了这个功能。
选项1:正常方式
from pydantic import BaseModel
class testclass(BaseModel):
value1: str = "a"
value2: str = "b"
test = testclass()
>>> print(test.json(indent=4))
{
"value1": "a",
"value2": "b"
}
选项2:使用pydantic的数据类
import json
from pydantic.dataclasses import dataclass
from pydantic.json import pydantic_encoder
@dataclass
class testclass:
value1: str = "a"
value2: str = "b"
test = testclass()
>>> print(json.dumps(test, indent=4, default=pydantic_encoder))
{
"value1": "a",
"value2": "b"
}
有一种方法非常适合我,你可以试试:
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__时,它特别好。这里是自动完成的。
到目前为止对我来说很好,期待你的想法。
我只会:
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)
你可以在json.dumps()函数中指定默认的命名参数:
json.dumps(obj, default=lambda x: x.__dict__)
解释:
从文档(2.7,3.6):
``default(obj)`` is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError.
(适用于Python 2.7和Python 3.x)
注意:在这种情况下,您需要实例变量而不是类变量,正如问题中的示例所尝试做的那样。(我假设请求者意味着类实例是类的对象)
我首先从@phihag的回答中了解到这一点。发现这是最简单、最干净的工作方式。
这里有两个简单的函数,用于序列化任何不复杂的类,没有前面解释的那么复杂。
我将此用于配置类型的东西,因为我可以向类添加新成员而无需进行代码调整。
import json
class SimpleClass:
def __init__(self, a=None, b=None, c=None):
self.a = a
self.b = b
self.c = c
def serialize_json(instance=None, path=None):
dt = {}
dt.update(vars(instance))
with open(path, "w") as file:
json.dump(dt, file)
def deserialize_json(cls=None, path=None):
def read_json(_path):
with open(_path, "r") as file:
return json.load(file)
data = read_json(path)
instance = object.__new__(cls)
for key, value in data.items():
setattr(instance, key, value)
return instance
# Usage: Create class and serialize under Windows file system.
write_settings = SimpleClass(a=1, b=2, c=3)
serialize_json(write_settings, r"c:\temp\test.json")
# Read back and rehydrate.
read_settings = deserialize_json(SimpleClass, r"c:\temp\test.json")
# results are the same.
print(vars(write_settings))
print(vars(read_settings))
# output:
# {'c': 3, 'b': 2, 'a': 1}
# {'c': 3, 'b': 2, 'a': 1}