2009-09-22 18 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 

C'è un modo per rendere serializzabile la mia classe json? La cosa che mi preoccupa è il riferimento ricorsivo.oggetti serializzabili Python json

+0

questa risposta potrebbe essere utile: http://stackoverflow.com/a/28253689/303114 – danfromisrael

+0

si mette in discussione il titolo è molto vago. Dovresti migliorarlo. –

+0

stessa domanda con una risposta chiusa: https://stackoverflow.com/a/7409526/2728644 – dasons

risposta

5

Risposta indiretta: invece di utilizzare JSON, è possibile utilizzare YAML, che non ha problemi a fare ciò che si desidera. (JSON è essenzialmente un sottoinsieme di YAML.)

Esempio:

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

Infatti, YAML gestisce ben riferimenti ciclici per voi.

+0

[Non scaricare mai i dati di cui non ti fidi!] (Http://nedbatchelder.com/blog/201302/war_is_peace .html) – Sardathrion

+1

Interessante articolo, ma non c'è * nessun disgiunzione * in questa risposta, solo * pickling * (cioè no 'load()', ma 'dump()'). – EOL

+1

In effetti, ma vale la pena tenerlo a mente. Inoltre, perché dovresti mettere qualcosa a meno che tu non preveda di usarlo più tardi? ... – Sardathrion

46

Scrivi la tua encoder e decoder, che può essere molto semplice come return __dict__

esempio ecco un encoder per eseguire il dump struttura ad albero totalmente ricorsiva, è possibile migliorare o utilizzare come lo è per il vostro scopo

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) 

esso stampa

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

si può allo stesso modo scrivere un decoder, ma lì si in qualche modo è necessario identificare se è il tuo oggetto o no, quindi potrebbe essere possibile inserire un tipo anche se necessario.

+2

Questo mi ha aiutato. Grazie. :) –

+1

La documentazione per simplejson dice esplicitamente che dovresti chiamare JSONEncoder.default() per generare TypeError, quindi penso che sarebbe meglio sostituire il tuo raise con una chiamata. – slacy

+0

O meglio ancora, implementa la tua sottoclasse '[semplice] json.JSONEncoder' e sovrascrivi il metodo' default' con una versione che restituisce una rappresentazione serializzabile dei tuoi oggetti o chiama 'JSONEncoder.default' per tutti gli altri tipi. Vedi http://docs.python.org/library/json.html#json.JSONEncoder. –

15

jsonpickle PER LA VITTORIA!

(Ho appena avuto questa stessa domanda ... json pickle gestisce grafici di oggetti ricorsivi/nidificati e cortocircuiti per grafici di oggetti ciclici).

+12

[Non scaricare mai i dati di cui non ti fidi!] (Http://nedbatchelder.com/blog/201302/war_is_peace.html) – Sardathrion

1

La mia soluzione per questo era estendere la classe 'dict' ed eseguire controlli sugli attributi richiesti/consentiti sovrascrivendo init, update e set di metodi di classe. utilizzo

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) 

Esempio:

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

ho implementato un metodo molto semplice todict con l'aiuto di https://stackoverflow.com/a/11637457/1766716

  • iterare su proprietà che non è inizia con __
  • Eliminare metodi
  • Eliminare manualmente alcune proprietà che non è necessario (per il mio caso, proveniente da sqlalcemy)

E utilizzato getattr per creare un dizionario.

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()} 
Problemi correlati