如何使一个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
当前回答
这是我的3美分… 这演示了一个树状python对象的显式json序列化。 注意:如果你真的想要这样的代码,你可以使用twisted FilePath类。
import json, sys, os
class File:
def __init__(self, path):
self.path = path
def isdir(self):
return os.path.isdir(self.path)
def isfile(self):
return os.path.isfile(self.path)
def children(self):
return [File(os.path.join(self.path, f))
for f in os.listdir(self.path)]
def getsize(self):
return os.path.getsize(self.path)
def getModificationTime(self):
return os.path.getmtime(self.path)
def _default(o):
d = {}
d['path'] = o.path
d['isFile'] = o.isfile()
d['isDir'] = o.isdir()
d['mtime'] = int(o.getModificationTime())
d['size'] = o.getsize() if o.isfile() else 0
if o.isdir(): d['children'] = o.children()
return d
folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)
其他回答
要添加另一个选项:您可以使用attrs包和asdict方法。
class ObjectEncoder(JSONEncoder):
def default(self, o):
return attr.asdict(o)
json.dumps(objects, cls=ObjectEncoder)
然后再转换回去
def from_json(o):
if '_obj_name' in o:
type_ = o['_obj_name']
del o['_obj_name']
return globals()[type_](**o)
else:
return o
data = JSONDecoder(object_hook=from_json).decode(data)
类看起来像这样
@attr.s
class Foo(object):
x = attr.ib()
_obj_name = attr.ib(init=False, default='Foo')
下面是一个简单功能的简单解决方案:
.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"
}
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/上获得
解决这个问题有很多方法。'ObjDict' (pip install object)是另一个。重点是提供像javascript一样的对象,它也可以像字典一样最好地处理从JSON加载的数据,但还有其他功能也很有用。这为原始问题提供了另一种解决方案。
除了Onur的答案,你可能想要处理如下的datetime类型。(以便处理:'datetime. time.)Datetime对象没有属性dict异常。)
def datetime_option(value):
if isinstance(value, datetime.date):
return value.timestamp()
else:
return value.__dict__
用法:
def toJSON(self):
return json.dumps(self, default=datetime_option, sort_keys=True, indent=4)