2009-09-22 9 views
27
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をシリアライズ可能にする方法はありますか?私が心配しているのは、再帰的な参照です。Pythonのシリアライズ可能なオブジェクトjson

+0

この回答は役に立つかもしれません: http://stackoverflow.com/a/28253689/303114あなたはタイトルは非常にあいまいで質問 – danfromisrael

+0

。あなたはそれを改善すべきです。 –

+0

同じ質問を閉じた回答:https://stackoverflow.com/a/7409526/2728644 – dasons

答えて

5

間接的な回答:JSONの代わりにYAMLを使用できます。これは問題なく動作します。 (JSONは本質的にYAMLのサブセットである。)

例:実際に

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

、YAMLはうまくあなたのための循環参照を処理します。

+0

[あなたが信頼していないデータを消去しないでください!](http://nedbatchelder.com/blog/201302/war_is_peace .html) – Sardathrion

+1

興味深い記事ですが、この回答には* unpickling *はありません。* pickling *のみです(つまり、load()ではなく 'dump()')。 – EOL

+1

確かにそれを覚えておく価値があります。それに、後で使う予定がない限り、なぜあなたは何かを漬けますか?... – Sardathrion

46

return __dict__

例えばのような非常に単純なことができ、独自のエンコーダとデコーダを書きますここでは完全に再帰的なツリー構造をダンプするエンコーダがあり、それはそれはあなたが同様のデコーダを書くことができますが、そこに必要になります

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

を印刷し、あなた自身の目的のために

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) 

であるとして、あなたはそれを強化するか、使用することができます何とかそれはあなたのオブジェクトであるかどうかを識別する必要があるので、必要に応じてタイプを入れることができるかもしれません。

+2

これは私を助けました。ありがとう。 :) –

+1

Simplejsonのドキュメントでは、JSONEncoder.default()を呼び出してTypeErrorを呼び出さなければならないと明示的に言われています。そのため、あなたのraiseをその呼び出しに置き換える方が良いと思います。 – slacy

+0

さらに、あなたの '[simple] json.JSONEncoder'サブクラスを実装し、' default'メソッドをオブジェクトの直列化表現を返すバージョンで上書きするか、他のすべての型の 'JSONEncoder.default'を呼び出します。 http://docs.python.org/library/json.html#json.JSONEncoderをご覧ください。 –

15

jsonpickle

(ちょうどこの同じ質問がありました... json pickleは再帰/ネストされたオブジェクトグラフと循環オブジェクトグラフの短絡を処理します)。

+12

[信頼していないデータを消去しないでください!](http://nedbatchelder.com/blog/201302/war_is_peace.html) – Sardathrion

1

私の解決策は、 'dict'クラスを拡張し、init、update、およびsetクラスメソッドをオーバーライドすることによって必須/許可属性のチェックを実行することでした。

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) 

使用例:

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" 
    } 
) 
1

私は、メソッドを排除__

  • で始まっていないプロパティを超えるhttps://stackoverflow.com/a/11637457/1766716

    • 反復の助けを借りて、非常に簡単なtodictメソッドを実装し
    • いくつかのプロパティを手動で削除する必要はありません(私の場合、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()} 
    
  • 関連する問題