Python 可序列化对象 json

33 投票
4 回答
53663 浏览
提问于 2025-04-15 14:30
class gpagelet:
    """
    Holds   1) the pagelet xpath, which is a string
            2) the list of pagelet shingles, list
    """
    def __init__(self, parent):
        if not isinstance( parent, gwebpage):
            raise Exception("Parent must be an instance of gwebpage")
        self.parent = parent    # This must be a gwebpage instance
        self.xpath = None       # String
        self.visibleShingles = [] # list of tuples
        self.invisibleShingles = [] # list of tuples
        self.urls = [] # list of string

class gwebpage:
    """
    Holds all the datastructure after the results have been parsed
    holds:  1) lists of gpagelets
            2) loc, string, location of the file that represents it
    """
    def __init__(self, url):
        self.url = url              # Str
        self.netloc = False         # Str
        self.gpagelets = []         # gpagelets instance
        self.page_key = ""          # str

有没有办法让我这个类可以转换成JSON格式?我担心的是会出现递归引用的问题。

4 个回答

3

我实现了一个非常简单的 todict 方法,参考了这个链接:https://stackoverflow.com/a/11637457/1766716

  • 遍历那些不以 __ 开头的属性
  • 去掉方法
  • 手动去掉一些不必要的属性(在我的情况下,这些属性来自 sqlalcemy)

然后我用 getattr 来构建字典。

class User(Base):
    id = Column(Integer, primary_key=True)
    firstname = Column(String(50))
    lastname = Column(String(50))
    password = Column(String(20))
    def props(self):
        return filter(
            lambda a:
            not a.startswith('__')
            and a not in ['_decl_class_registry', '_sa_instance_state', '_sa_class_manager', 'metadata']
            and not callable(getattr(self, a)),
            dir(self))
    def todict(self):
        return {k: self.__getattribute__(k) for k in self.props()}
6

间接的回答是:与其使用JSON,不如试试YAML,它可以很好地满足你的需求。(其实,JSON可以看作是YAML的一部分。)

举个例子:

import yaml
o1 = gwebpage("url")
o2 = gpagelet(o1)
o1.gpagelets = [o2]
print yaml.dump(o1)

实际上,YAML可以很方便地处理循环引用的问题。

53

自己写一个编码器和解码器,这个过程可以非常简单,比如你可以用 return __dict__ 这样的代码。

例如,这里有一个编码器,可以把完全递归的树结构输出,你可以根据自己的需要进行改进,或者直接使用它。

import json

class Tree(object):
    def __init__(self, name, childTrees=None):
        self.name = name
        if childTrees is None:
            childTrees = []
        self.childTrees = childTrees

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if not isinstance(obj, Tree):
            return super(MyEncoder, self).default(obj)

        return obj.__dict__

c1 = Tree("c1")
c2 = Tree("c2") 
t = Tree("t",[c1,c2])

print json.dumps(t, cls=MyEncoder)

它会打印出

{"childTrees": [{"childTrees": [], "name": "c1"}, {"childTrees": [], "name": "c2"}], "name": "t"}

你也可以类似地写一个解码器,但在那里面你需要找出这个对象是不是你自己定义的,所以如果需要的话,可以加一个类型标识。

撰写回答