如何使一个Python类序列化?
class FileItem:
def __init__(self, fname):
self.fname = fname
尝试序列化为JSON:
>>> import json
>>> x = FileItem('/foo/bar')
>>> json.dumps(x)
TypeError: Object of type 'FileItem' is not JSON serializable
如何使一个Python类序列化?
class FileItem:
def __init__(self, fname):
self.fname = fname
尝试序列化为JSON:
>>> import json
>>> x = FileItem('/foo/bar')
>>> json.dumps(x)
TypeError: Object of type 'FileItem' is not JSON serializable
当前回答
这个类可以做到这一点,它将object转换为标准json。
import json
class Serializer(object):
@staticmethod
def serialize(object):
return json.dumps(object, default=lambda o: o.__dict__.values()[0])
用法:
Serializer.serialize(my_object)
在python2.7和python3中工作。
其他回答
这个函数使用递归迭代遍历字典的每个部分,然后调用非内置类型类的repr()方法。
def sterilize(obj):
object_type = type(obj)
if isinstance(obj, dict):
return {k: sterilize(v) for k, v in obj.items()}
elif object_type in (list, tuple):
return [sterilize(v) for v in obj]
elif object_type in (str, int, bool, float):
return obj
else:
return obj.__repr__()
Kyle Delaney的评论是正确的,所以我尝试使用https://stackoverflow.com/a/15538391/1497139以及https://stackoverflow.com/a/10254820/1497139的改进版本
创建一个“JSONAble”mixin。
因此,要使一个类JSON可序列化使用“JSONAble”作为超类,并调用:
instance.toJSON()
or
instance.asJSON()
对于这两种方法。您还可以使用本文提供的其他方法扩展JSONAble类。
家庭和个人单元测试样本的测试示例结果如下:
toJSOn ():
{
"members": {
"Flintstone,Fred": {
"firstName": "Fred",
"lastName": "Flintstone"
},
"Flintstone,Wilma": {
"firstName": "Wilma",
"lastName": "Flintstone"
}
},
"name": "The Flintstones"
}
asJSOn ():
{'name': 'The Flintstones', 'members': {'Flintstone,Fred': {'firstName': 'Fred', 'lastName': 'Flintstone'}, 'Flintstone,Wilma': {'firstName': 'Wilma', 'lastName': 'Flintstone'}}}
使用家庭和个人样本进行单元测试
def testJsonAble(self):
family=Family("The Flintstones")
family.add(Person("Fred","Flintstone"))
family.add(Person("Wilma","Flintstone"))
json1=family.toJSON()
json2=family.asJSON()
print(json1)
print(json2)
class Family(JSONAble):
def __init__(self,name):
self.name=name
self.members={}
def add(self,person):
self.members[person.lastName+","+person.firstName]=person
class Person(JSONAble):
def __init__(self,firstName,lastName):
self.firstName=firstName;
self.lastName=lastName;
JSONAble .py定义JSONAble mixin
'''
Created on 2020-09-03
@author: wf
'''
import json
class JSONAble(object):
'''
mixin to allow classes to be JSON serializable see
https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable
'''
def __init__(self):
'''
Constructor
'''
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
def getValue(self,v):
if (hasattr(v, "asJSON")):
return v.asJSON()
elif type(v) is dict:
return self.reprDict(v)
elif type(v) is list:
vlist=[]
for vitem in v:
vlist.append(self.getValue(vitem))
return vlist
else:
return v
def reprDict(self,srcDict):
'''
get my dict elements
'''
d = dict()
for a, v in srcDict.items():
d[a]=self.getValue(v)
return d
def asJSON(self):
'''
recursively return my dict elements
'''
return self.reprDict(self.__dict__)
您将发现这些方法现在集成在https://github.com/WolfgangFahl/pyLoDStorage项目中,该项目可在https://pypi.org/project/pylodstorage/上获得
下面是一个简单功能的简单解决方案:
.toJSON()方法
实现一个序列化器方法,而不是一个JSON可序列化类:
import json
class Object:
def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__,
sort_keys=True, indent=4)
所以你只需调用它来序列化:
me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"
print(me.toJSON())
将输出:
{
"age": 35,
"dog": {
"name": "Apollo"
},
"name": "Onur"
}
解决这个问题有很多方法。'ObjDict' (pip install object)是另一个。重点是提供像javascript一样的对象,它也可以像字典一样最好地处理从JSON加载的数据,但还有其他功能也很有用。这为原始问题提供了另一种解决方案。
另一种选择是将JSON转储打包到它自己的类中:
import json
class FileItem:
def __init__(self, fname):
self.fname = fname
def __repr__(self):
return json.dumps(self.__dict__)
或者,更好的是,从JsonSerializable类继承FileItem类:
import json
class JsonSerializable(object):
def toJson(self):
return json.dumps(self.__dict__)
def __repr__(self):
return self.toJson()
class FileItem(JsonSerializable):
def __init__(self, fname):
self.fname = fname
测试:
>>> f = FileItem('/foo/bar')
>>> f.toJson()
'{"fname": "/foo/bar"}'
>>> f
'{"fname": "/foo/bar"}'
>>> str(f) # string coercion
'{"fname": "/foo/bar"}'