Python可序列化对象json

Python serializable objects json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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序列化?我担心的是递归引用。


编写自己的编码器和解码器,这很简单,就像return __dict__

例如,这里有一个编码器来转储完全递归的树结构,您可以增强它,也可以根据自己的目的使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)

它打印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{"childTrees": [{"childTrees": [],"name":"c1
<div class="
suo-content">[collapse title=""]<ul><li>这对我有帮助。谢谢。:)</li><li>simplejson的文档明确指出,应该调用jsonEncoder.default()来引发typeError,所以我认为最好用调用来替换您的raise。</li><li>或者更好的方法是,实现自己的<wyn>[simple]json.JSONEncoder</wyn>子类,并使用返回对象的可序列化表示形式或为所有其他类型调用<wyn>JSONEncoder.default</wyn>的版本覆盖<wyn>default</wyn>方法。参见docs.python.org/library/json.html json.jsonencoder。</li><li>@克丽萨恩特,这不是阿努拉格上面的方法所做的吗?</li><li>@我的评论比最后一次编辑的答案要旧,所以我可能指的是更早的版本。</li></ul>[/collapse]</div><hr>
<p>
jsonpickle FOR THE WIN!
</p>

<p>
(Just had this same question... json pickle handles recursive/nested object graphs as well as short circuits for cyclical object graphs).
</p>

<div class="
suo-content">[collapse title=""]<ul><li>不要拆掉你不信任的数据!</li></ul>[/collapse]</div><p><center>[wp_ad_camp_1]</center></p><hr><P>间接回答:您可以使用yaml,而不是使用json,这样做没有问题。(json本质上是yaml的一个子集。)</P><P>例子:</P>[cc lang="python"]import yaml
o1 = gwebpage("
url")
o2 = gpagelet(o1)
o1.gpagelets = [o2]
print yaml.dump(o1)

实际上,yaml很好地为您处理循环引用。


在https://stackoverflow.com/a/11637457/1766716的帮助下,我实现了一个非常简单的todict方法。

  • 迭代不以__开头的属性
  • 消除方法
  • 手动删除一些不必要的属性(对于我的情况,来自sqlacalcemy)

并用getattr建立字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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()}

My solution for this was to extend the 'dict' class and perform checks around required/allowed attributes by overriding init, update, and set class methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class StrictDict(dict):
    required=set()
    at_least_one_required=set()
    cannot_coexist=set()
    allowed=set()
    def __init__(self, iterable={}, **kwargs):
        super(StrictDict, self).__init__({})
        keys = set(iterable.keys()).union(set(kwargs.keys()))
        if not keys.issuperset(self.required):
            msg = str(self.__class__.__name__) +" requires:" + str([str(key) for key in self.required])
            raise AttributeError(msg)
        if len(list(self.at_least_one_required)) and len(list(keys.intersection(self.at_least_one_required))) < 1:
            msg = str(self.__class__.__name__) +" requires at least one:" + str([str(key) for key in self.at_least_one_required])
            raise AttributeError(msg)
        for key, val in iterable.iteritems():
            self.__setitem__(key, val)
        for key, val in kwargs.iteritems():
            self.__setitem__(key, val)

    def update(self, E=None, **F):
        for key, val in E.iteritems():
            self.__setitem__(key, val)
        for key, val in F.iteritems():
            self.__setitem__(key, val)
        super(StrictDict, self).update({})

    def __setitem__(self, key, value):
        all_allowed = self.allowed.union(self.required).union(self.at_least_one_required).union(self.cannot_coexist)
        if key not in list(all_allowed):
            msg = str(self.__class__.__name__) +" does not allow member '" + key +"'"
            raise AttributeError(msg)
        if key in list(self.cannot_coexist):
            for item in list(self.cannot_coexist):
                if key != item and item in self.keys():
                    msg = str(self.__class__.__name__) +"does not allow members '" + key +"' and '" + item +"' to coexist'"
                    raise AttributeError(msg)
        super(StrictDict, self).__setitem__(key, value)

示例用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class JSONDoc(StrictDict):
   """
    Class corresponding to JSON API top-level document structure
    http://jsonapi.org/format/#document-top-level
   """

    at_least_one_required={'data', 'errors', 'meta'}
    allowed={"jsonapi","links","included"}
    cannot_coexist={"data","errors"}
    def __setitem__(self, key, value):
        if key =="included" and"data" not in self.keys():
            msg = str(self.__class__.__name__) +" does not allow 'included' member if 'data' member is not present"
            raise AttributeError(msg)
        super(JSONDoc, self).__setitem__(key, value)

json_doc = JSONDoc(
    data={
       "id": 5,
       "type":"movies"
    },
    links={
       "self":"http://url.com"
    }
)