lmo*_*tl3 13 serialization json decoder python-3.x
就像标题所说的那样,我正在尝试为我已定义的类包含其他类我定义的对象的对象编写自定义解码器."外部"类是Edge,定义如下:
class Edge:
def __init__(self, actor, movie):
self.actor = actor
self.movie = movie
def __eq__(self, other):
if (self.movie == other.movie) & (self.actor == other.actor):
return True
else:
return False
def __str__(self):
print("Actor: ", self.actor, " Movie: ", self.movie)
def get_actor(self):
return self.actor
def get_movie(self):
return self.movie
Run Code Online (Sandbox Code Playgroud)
与"内部"类的actor和电影定义如下:
class Movie:
def __init__(self, title, gross, soup, year):
self.title = title
self.gross = gross
self.soup = soup
self.year = year
def __eq__(self, other):
if self.title == other.title:
return True
else:
return False
def __repr__(self):
return self.title
def __str__(self):
return self.title
def get_gross(self):
return self.gross
def get_soup(self):
return self.soup
def get_title(self):
return self.title
def get_year(self):
return self.year
class Actor:
def __init__(self, name, age, soup):
self.name = name
self.age = age
self.soup = soup
def __eq__(self, other):
if self.name == other.name:
return True
else:
return False
def __repr__(self):
return self.name
def __str__(self):
return self.name
def get_age(self):
return self.age
def get_name(self):
return self.name
def get_soup(self):
return self.soup
Run Code Online (Sandbox Code Playgroud)
(汤只是该电影/演员的维基百科页面的美丽对象,它可以被忽略).我也为边缘类编写了一个客户编码器:
class EdgeEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, Edge):
return {
"Actor": {
"Name": o.get_actor().get_name(),
"Age": o.get_actor().get_age()
},
"Movie": {
"Title": o.get_movie().get_title(),
"Gross": o.get_movie().get_gross(),
"Year": o.get_movie().get_year()
}
}
return json.JSONEncoder.default(self, o)
Run Code Online (Sandbox Code Playgroud)
我已经测试过,它正确地将边缘列表序列化为JSON文件.现在我的问题出现在尝试编写边缘解码器时.我在这里使用了github页面作为参考,但我的编码器偏离了他,我想知道是否有必要改变它.我是否需要在其JSON序列化中将对象的类型显式编码为其自己的键值对,或者是否有某种方法可以通过边缘的序列化来获取"Actor"和"Movie"键?同样,有没有办法获取"名称"."Age"等,这样我可以重建Actor/Movie对象,然后使用它们重建边缘?有没有更好的方法来编码我的对象?我也尝试过这个教程,但是我发现对象dicts的使用让他们的编码器感到困惑,我不知道如何将该方法扩展到包含自定义对象的自定义对象.
您引用的编码器/解码器示例(此处)可以轻松扩展以允许 JSON 输入/输出中的不同类型的对象。
但是,如果您只想要一个简单的解码器来匹配您的编码器(仅在 JSON 文件中编码 Edge 对象),请使用此解码器:
class EdgeDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, dct):
if 'Actor' in dct:
actor = Actor(dct['Actor']['Name'], dct['Actor']['Age'], '')
movie = Movie(dct['Movie']['Title'], dct['Movie']['Gross'], '', dct['Movie']['Year'])
return Edge(actor, movie)
return dct
Run Code Online (Sandbox Code Playgroud)
使用问题中的代码定义 classes Movie, Actor, Edge, and EdgeEncoder,以下代码将输出一个测试文件,然后将其读回:
filename='test.json'
movie = Movie('Python', 'many dollars', '', '2000')
actor = Actor('Casper Van Dien', 49, '')
edge = Edge(actor, movie)
with open(filename, 'w') as jsonfile:
json.dump(edge, jsonfile, cls=EdgeEncoder)
with open(filename, 'r') as jsonfile:
edge1 = json.load(jsonfile, cls=EdgeDecoder)
assert edge1 == edge
Run Code Online (Sandbox Code Playgroud)
use*_*078 -2
这个问题无需使用JSONEncoder或即可解决JSONDecoder。
to_dict()方法(负责从python object到 的转换JSON dict)bool, str, int, and float检查传递的参数是否为 类型dict,如果是这种情况,您必须自己构造该对象(请参阅 的构造函数Edge)稍微缩短一下你的例子:
class Edge:
def __init__(self, actor, movie):
if type(actor) is Actor:
self.actor = actor
else: # type == dict
self.actor = Actor(**actor)
if type(movie) is Movie:
self.movie = movie
else: # type == dict
self.movie = Movie(**movie)
def __eq__(self, other):
return (self.movie == other.movie) & (self.actor == other.actor)
def __str__(self):
return "".join(["Actor: ", str(self.actor), " /// Movie: ", str(self.movie)])
def to_dict(self):
return {"actor": self.actor.to_dict(), "movie": self.movie.to_dict()}
class Movie:
def __init__(self, title, gross, soup, year):
self.title = title
self.gross = gross
self.soup = soup
self.year = year
def __eq__(self, other):
return self.title == other.title
def __str__(self):
return self.title
def to_dict(self):
return {"title": self.title, "gross": self.gross, "soup": self.soup, "year": self.year}
class Actor:
def __init__(self, name, age, soup):
self.name = name
self.age = age
self.soup = soup
def __eq__(self, other):
return self.name == other.name
def __str__(self):
return self.name
def to_dict(self):
return {"name": self.name, "age": self.age, "soup": self.soup}
if __name__ == '__main__':
edge_obj = Edge(Actor("Pierfrancesco Favino", 50, "id0"), Movie("Suburra", 10, "id1", 2015))
edge_dict = edge_obj.to_dict()
edge_obj_new = Edge(**edge_dict)
print("manual edge\t\t", edge_obj)
print("edge to json\t", edge_dict)
print("auto edge\t\t", edge_obj_new)
print("edges equal?\t", edge_obj == edge_obj_new)
Run Code Online (Sandbox Code Playgroud)
返回:
manual edge Actor: Pierfrancesco Favino /// Movie: Suburra
edge to json {'actor': {'name': 'Pierfrancesco Favino', 'age': 50, 'soup': 'id0'}, 'movie': {'title': 'Suburra', 'gross': 10, 'soup': 'id1', 'year': 2015}}
auto edge Actor: Pierfrancesco Favino /// Movie: Suburra
edges equal? True
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,两个Edge对象是相等的,第二行Edge以符号形式dict输出JSON。
| 归档时间: |
|
| 查看次数: |
4016 次 |
| 最近记录: |