Objek serialisasi Python json

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

Apakah ada cara bagi saya untuk membuat kelas json saya dapat diserialkan? Hal yang saya khawatirkan adalah referensi rekursif.


person Community    schedule 22.09.2009    source sumber
comment
jawaban ini mungkin bisa membantu: stackoverflow.com/a/28253689/303114   -  person danfromisrael    schedule 09.04.2015
comment
judul pertanyaan Anda sangat kabur. Anda harus memperbaikinya.   -  person Charlie Parker    schedule 04.02.2017
comment
pertanyaan yang sama dengan jawaban tertutup: stackoverflow.com/a/7409526/2728644   -  person dasons    schedule 03.06.2017


Jawaban (5)


Tulis encoder dan decoder Anda sendiri, yang bisa sangat sederhana seperti return __dict__

misalnya di sini adalah pembuat enkode untuk membuang struktur pohon yang benar-benar rekursif, Anda dapat menyempurnakannya atau menggunakannya sebagaimana adanya untuk tujuan Anda sendiri

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)

itu mencetak

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

Anda juga dapat menulis dekoder tetapi di sana Anda perlu mengidentifikasi apakah itu objek Anda atau bukan, jadi mungkin Anda dapat memasukkan tipenya juga jika diperlukan.

person Anurag Uniyal    schedule 22.09.2009
comment
Dokumentasi untuk simplejson secara eksplisit mengatakan bahwa Anda harus memanggil JSONEncoder.default() untuk menaikkan TypeError, jadi menurut saya akan lebih baik untuk mengganti kenaikan gaji Anda dengan panggilan ke sana. - person slacy; 03.01.2012
comment
Atau bahkan lebih baik lagi, implementasikan subkelas [simple]json.JSONEncoder Anda sendiri dan timpa metode default dengan versi yang mengembalikan representasi objek Anda yang dapat diserialkan atau panggil JSONEncoder.default untuk semua tipe lainnya. Lihat docs.python.org/library/json.html#json.JSONEncoder. - person Chris Arndt; 23.01.2012
comment
@ChrisArndt bukankah itu yang dilakukan metode Anurag di atas? - person zakdances; 03.03.2013
comment
@yourfiendzak Komentar saya lebih lama dari jawaban edit terakhir, jadi saya mungkin merujuk ke versi sebelumnya. - person Chris Arndt; 19.03.2013

jsonpickle UNTUK MENANG!

(Baru saja mendapat pertanyaan yang sama... acar json menangani grafik objek rekursif/bersarang serta sirkuit pendek untuk grafik objek siklis).

person longda    schedule 13.06.2012
comment
Jangan pernah membongkar data yang tidak Anda percayai! - person Sardathrion - against SE abuse; 04.02.2013

Jawaban tidak langsung: daripada menggunakan JSON, Anda dapat menggunakan YAML, yang tidak memiliki masalah dalam melakukan apa yang Anda inginkan. (JSON pada dasarnya adalah bagian dari YAML.)

Contoh:

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

Faktanya, YAML menangani referensi siklik dengan baik untuk Anda.

person Eric O Lebigot    schedule 22.09.2009
comment
Jangan pernah membongkar data yang tidak Anda percayai! - person Sardathrion - against SE abuse; 04.02.2013
comment
Artikel yang menarik, tetapi tidak ada unpickling dalam jawaban ini, hanya pickling (yaitu tidak ada load(), tapi dump()). - person Eric O Lebigot; 05.02.2013
comment
Memang benar, tetapi perlu diingat. Selain itu, mengapa Anda membuat acar sesuatu kecuali Anda berencana menggunakannya nanti?... - person Sardathrion - against SE abuse; 05.02.2013
comment
Memang. Namun, sangat aman untuk load() YAML dumped dengan kode di atas (tidak dapat mengarah pada interpretasi kode Python, kecuali ada bug di PyYAML, seperti yang ditunjukkan kode sumber [tidak ada injeksi kode Python… ]). - person Eric O Lebigot; 05.02.2013
comment
Ya, kami sepakat: aman dalam kasus ini namun belum tentu dalam semua kasus. Saya menjadi paranoid dan memperkirakan penggunaan contoh Anda. Jadi hanya (yang awalnya) sebuah komentar kecil. - person Sardathrion - against SE abuse; 05.02.2013

Saya menerapkan metode todict yang sangat sederhana dengan bantuan https://stackoverflow.com/a/11637457/1766716

  • Ulangi properti yang tidak dimulai dengan __
  • Hilangkan metode
  • Hilangkan beberapa properti secara manual yang tidak diperlukan (untuk kasus saya, berasal dari sqlalcemy)

Dan menggunakan getattr untuk membuat kamus.

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()}
person guneysus    schedule 06.03.2016

Solusi saya untuk ini adalah memperluas kelas 'dict' dan melakukan pemeriksaan seputar atribut yang diperlukan/diizinkan dengan mengganti metode kelas init, update, dan 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)

Contoh penggunaan:

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"
    }
)
person g.carey    schedule 25.06.2015