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序列化?我担心的是递归引用。
编写自己的编码器和解码器,这很简单,就像
例如,这里有一个编码器来转储完全递归的树结构,您可以增强它,也可以根据自己的目的使用它。
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的帮助下,我实现了一个非常简单的
- 迭代不以
__ 开头的属性 - 消除方法
- 手动删除一些不必要的属性(对于我的情况,来自sqlacalcemy)
并用
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" } ) |
。