首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何为复杂对象编写自定义JSON解码器?

如何为复杂对象编写自定义JSON解码器?
EN

Stack Overflow用户
提问于 2018-02-26 23:35:04
回答 1查看 13.1K关注 0票数 21

正如标题所说,我正在尝试为我定义了类的对象编写一个自定义解码器,其中包含我定义的类的其他对象。"outer“类是一个Edge类,定义如下:

代码语言:javascript
复制
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

在“内部”类中,演员和电影的定义如下:

代码语言:javascript
复制
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

(soup只是电影/演员维基百科页面的一个漂亮的soup对象,可以忽略它)。我也为edge类编写了一个客户编码器:

代码语言:javascript
复制
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)

我已经测试过了,它可以正确地将边缘列表序列化为JSON文件。现在我的问题来了,当我试图写一个边缘解码器。我使用了github页面的here作为参考,但我的编码器与他的有所不同,我想知道是否有必要更改它。我是否需要像他那样在JSON序列化中显式地将对象的类型编码为它自己的键值对,或者有什么方法可以通过序列化边缘来获取"Actor“和"Movie”键?同样,有没有办法获取“名字”。"Age",等等,这样我就可以重建Actor/Movie对象,然后用它们来重建边缘?有没有更好的方法来编码我的对象呢?我也尝试过遵循this教程,但我发现对象字典的使用对编码器来说很混乱,而且我不确定如何将该方法扩展到包含自定义对象的自定义对象。

EN

回答 1

Stack Overflow用户

发布于 2018-09-04 01:41:32

您引用的编码器/解码器示例(here)可以很容易地进行扩展,以允许在JSON输入/输出中使用不同类型的对象。

但是,如果您只想要一个简单的解码器来匹配您的编码器(仅在JSON文件中对Edge对象进行编码),请使用此解码器:

代码语言:javascript
复制
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

使用问题中的代码来定义类MovieActorEdgeEdgeEncoder,下面的代码将输出一个测试文件,然后读回它:

代码语言:javascript
复制
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
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48991911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档