JSON sinfini qanday qilib seriyali qilish mumkin

Python sinfini qanday qilib serializatsiya qilish mumkin?

Oddiy sinf:

class FileItem:
    def __init__(self, fname):
        self.fname = fname

Natijani olish uchun nima qilishim kerak:

>>> import json

>>> my_file = FileItem('/foo/bar')
>>> json.dumps(my_file)
TypeError: Object of type 'FileItem' is not JSON serializable

Xatosiz


person Sergey    schedule 22.09.2010    source manba
comment
Afsuski, barcha javoblar sinfni qanday qilib ketma-ketlashtirish mumkin? Harakat savolidan ko'ra, sinfni qanday qilib serializatsiya qilish mumkin? Bu javoblar ob'ektni ketma-ketlashtiradigan boshqa modulga o'tkazish o'rniga, o'zingiz ketma-ketlashtirishni amalga oshirayotganingizni taxmin qiladi.   -  person Kyle Delaney    schedule 18.10.2019
comment
Agar siz Python3.5+ dan foydalansangiz, jsons dan foydalanishingiz mumkin. U ob'ektingizni (va uning barcha atributlarini rekursiv) dictga aylantiradi. import jsons quyidagi javobga qarang - u juda yaxshi ishlaydi   -  person tswaehn    schedule 02.04.2020
comment
@KyleDelaney Men haqiqatan ham dengizga ulanish uchun amalga oshirishim mumkin bo'lgan interfeys/sehrli usulga umid qilgandim. O'ylaymanki, .to_dict() funksiyasini yoki uni ketma-ketlashtirishga harakat qiladigan modulga o'tishdan oldin ob'ektga chaqirilishi mumkin bo'lgan narsalarni amalga oshirishim kerak.   -  person Felix B.    schedule 01.09.2020
comment
JSONAble mixini boshlash uchun stackoverflow.com/a/63718624/1497139 ga qarang.   -  person Wolfgang Fahl    schedule 03.09.2020
comment
@FelixB. Siz o'rnatilgan vars funksiyasidan json.dumps bilan birgalikda foydalanishingiz mumkin (mening javobimga qarang stackoverflow.com/a/64469761/1587520 )   -  person user1587520    schedule 23.11.2020


Javoblar (33)


Kutilayotgan natija haqida fikringiz bormi? Masalan, bu amalga oshadimi?

>>> f  = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'

Bunday holda siz shunchaki json.dumps(f.__dict__) raqamiga qo'ng'iroq qilishingiz mumkin.

Agar siz ko'proq moslashtirilgan chiqishni istasangiz, unda siz JSONEncoder kichik sinfiga kirishingiz va amalga oshirishingiz kerak bo'ladi. o'zingizning shaxsiy serializatsiyangiz.

Arzimas misol uchun, pastga qarang.

>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
        def default(self, o):
            return o.__dict__    

>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'

Keyin siz ushbu sinfni json.dumps() usuliga cls kwarg sifatida o'tkazasiz:

json.dumps(cls=MyEncoder)

Agar siz ham dekodlashni istasangiz, JSONDecoder uchun maxsus object_hook ni taqdim etishingiz kerak bo‘ladi. sinf. Masalan:

>>> def from_json(json_object):
        if 'fname' in json_object:
            return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>> 
person Manoj Govindan    schedule 22.09.2010
comment
__dict__ dan foydalanish hamma hollarda ham ishlamaydi. Ob'ekt yaratilgandan keyin atributlar o'rnatilmagan bo'lsa, __dict__ to'liq to'ldirilmasligi mumkin. Yuqoridagi misolda siz yaxshisiz, lekin sizda kodlamoqchi bo'lgan sinf atributlari bo'lsa, ular sinfning __init__ chaqiruvida yoki ob'ekt paydo bo'lgandan keyin boshqa yo'l bilan o'zgartirilmagan bo'lsa, __dict__ ro'yxatiga kiritilmaydi. yaratilgan. - person Kris Hardy; 29.12.2011
comment
+1, lekin ob'ekt kancasi sifatida ishlatiladigan from_json() funktsiyasi else: return json_object bayonotiga ega bo'lishi kerak, shuning uchun u umumiy ob'ektlar bilan ham ishlay oladi. - person jogojapan; 19.03.2013
comment
Agar siz yangi uslublar sinfida __slots__ dan foydalansangiz @KrisHardy __dict__ ham ishlamaydi. - person badp; 13.12.2013
comment
Maxsus protokol yaratish uchun yuqoridagi kabi maxsus JSONEncoder dan foydalanishingiz mumkin, masalan, __json_serializable__ usuli mavjudligini tekshirish va ob'ektning JSON seriyali tasvirini olish uchun uni chaqirish. Bu __getitem__, __str__, __eq__ va __len__ kabi boshqa Python naqshlariga mos keladi. - person jpmc26; 15.07.2015
comment
Men python uchun yangiman... biz ushbu kutubxonalardan (json yoki simplejson) python ishlab chiquvchilari tomonidan keng qo'llaniladigan ob'ektlarni seriyalash/seriyadan chiqarish uchun foydalana olamizmi, deyishadi, pandas dataframe, series va hokazo? - person Mahesha999; 20.09.2016
comment
__dict__ ham rekursiv ishlamaydi, masalan, ob'ektingizning atributi boshqa ob'ekt bo'lsa. - person Neel; 10.04.2018
comment
JSONEncoder agar berilgan ma'lumotlar nostandart bo'lsa, faqat kichik sinfning default usulini chaqiradi. - person yoonghm; 18.09.2018
comment
@Mahesha999 Dataframe, Series va boshqalar uchun df.to_json() usulidan foydalaning - person user2561747; 07.12.2018

Mana oddiy xususiyat uchun oddiy yechim:

.toJSON() Usul

JSON seriyali sinf o'rniga serializator usulini qo'llang:

import json

class Object:
    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, 
            sort_keys=True, indent=4)

Shunday qilib, siz uni seriyali qilish uchun chaqirasiz:

me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"

print(me.toJSON())

chiqadi:

{
    "age": 35,
    "dog": {
        "name": "Apollo"
    },
    "name": "Onur"
}
person Onur Yıldırım    schedule 21.03.2013
comment
Juda cheklangan. Agar sizda {foo:bar,baz:bat} dict bo'lsa, u JSON-ga osongina seriyalanadi. Agar uning o'rniga sizda {foo:bar,baz:MyObject()} bo'lsa, qila olmaysiz. Ideal holat shundaki, ichki o'rnatilgan ob'ektlar JSONga aniq emas, balki rekursiv tarzda seriyalashtiriladi. - person Mark E. Haase; 22.08.2013
comment
Bu hali ham ishlaydi. Sizga o.__dict___ yetishmayapti. O'zingizning misolingizni sinab ko'ring: class MyObject(): def __init__(self): self.prop = 1 j = json.dumps({ "foo": "bar", "baz": MyObject() }, default=lambda o: o.__dict__) - person Onur Yıldırım; 23.08.2013
comment
Bu yechim qayta tiklanadimi? ya'ni Ob'ektni json'dan qayta qurish osonmi? - person Jorge Leitao; 26.04.2015
comment
@J.C.Leitão Yo'q. Siz bir xil maydonlarga ega bo'lgan ikki xil sinfga ega bo'lishingiz mumkin. Ushbu sinfning a va b ob'ektlari (ehtimol bir xil xususiyatlarga ega) bir xil a.__dict__ / b.__dict__ ga ega bo'ladi. - person Martin Thoma; 16.06.2015
comment
Shu bilan birga, siz ob'ektning dastlab qaysi sinfga ega ekanligini ko'rsatadigan unjson_class yoki shunga o'xshash maydonni qo'shishingiz mumkin. Keyin modulning introspektsiyasidan foydalanishingiz va ob'ektni qaytarib olish uchun stackoverflow.com/a/2169191/562769 kabi narsalarni ishlatishingiz mumkin. . - person Martin Thoma; 16.06.2015
comment
Bu datetime.datetime misol bilan ishlamaydi. U quyidagi xatoni keltirib chiqaradi: 'datetime.datetime' object has no attribute '__dict__' - person Bruno Finger; 17.06.2015
comment
Quyidagilar __dict__ ga ega bo'lmagan har qanday narsa uchun ishlaydi: def _try(o): try: return o.__dict__ except: return str(o) va def to_JSON(self): return json.dumps(self, default=lambda o: _try(o), sort_keys=True, indent=0, separators=(',',':')).replace('\n', '') - person Bruno Finger; 17.06.2015
comment
@J.C.Leitão ha, bu teskari. json-ni yuklaganingizda, har bir kalit/qiymat juftligini ob'ekt dict xususiyatiga qo'shishingiz mumkin, qarang: stackoverflow.com/questions/6578986/ - person FistOfFury; 03.09.2017
comment
Menga biror narsa etishmayotgan bo'lsa kerak, lekin u ishlamayapti shekilli (ya'ni, json.dumps(me) Object ning toJSON usulini chaqirmaydi. - person cglacet; 24.08.2018
comment
default=lambda o: o.__dict__ oʻrniga default=vars dan foydalanishingiz mumkin. - person Matthew D. Scholefield; 24.02.2019
comment
@cglacet Buning sababi, u sinfni ketma-ketlashtirmagani uchun, u faqat JSON Stringni tupuradigan usulni yaratdi. Bu savolga to'g'ri javob emas, bu ko'proq maxsus holatlar uchun xakerlikdir. Lekin to'g'risi yuqorida. Agar sizga YourObject-ni boshqa ParentObject-ning bir qismi/tarkibida ketma-ketlashtirish kerak bo'lsa, kodlovchi yaratishingiz kerak. - person Javo; 08.09.2020
comment
Savol, ayniqsa json.dumps() ni yaratish haqida so'raydi. JSON serializatsiyasini o'zingiz qanday amalga oshirishingiz mumkin emas. - person Ernest; 23.10.2020

Murakkab sinflar uchun jsonpickle vositasini ko'rib chiqishingiz mumkin:

jsonpickle - bu JSON-ga va JSON-dan murakkab Python obyektlarini ketma-ketlashtirish va seriyadan chiqarish uchun Python kutubxonasi.

Python-ni JSON-ga kodlash uchun standart Python kutubxonalari, masalan, stdlib's json, simplejson va demjson, faqat to'g'ridan-to'g'ri JSON ekvivalentiga ega bo'lgan Python primitivlarini (masalan, dicts, lists, strings, ints, va hokazo) ishlay oladi. jsonpickle ushbu kutubxonalar ustiga quriladi va yanada murakkab ma'lumotlar tuzilmalarini JSONga seriyalashtirishga imkon beradi. jsonpickle juda sozlanishi va kengaytirilishi mumkin - bu foydalanuvchiga JSON backend-ni tanlash va qo'shimcha backendlarni qo'shish imkonini beradi.

(PyPi-da jsonpickle havolasi)

person gecco    schedule 23.12.2011
comment
C# dan kelib chiqqan holda, men kutgan narsa shu edi. Oddiy bitta layner va sinflar bilan aralashmaslik. - person Jerther; 14.12.2015
comment
jsonpickle ajoyib. U juda ko'p darajali sinflarga ega ulkan, murakkab, tartibsiz ob'ekt uchun juda yaxshi ishladi - person wisbucky; 04.03.2016
comment
buni faylga saqlashning to'g'ri usuliga misol bormi? Hujjatlar faqat jsonpickle ob'ektini qanday kodlash va dekodlashni ko'rsatadi. Bundan tashqari, bu pandalar ma'lumotlar ramkalarini o'z ichiga olgan diktlarni dekodlay olmadi. - person user5359531; 16.08.2016
comment
@ user5359531 obj = jsonpickle.decode(file.read()) va file.write(jsonpickle.encode(obj)) dan foydalanishingiz mumkin. - person Kilian Batzner; 02.01.2017
comment
Django uchun maxsus savol: seans ma'lumotlarini ketma-ketlashtirish uchun jsonpickle-dan foydalanish tuzlangan kabi zaiflikka egami? (bu yerda tasvirlanganidek https://docs.djangoproject.com/en/1.11/topics/http/sessions/#bundled-serializers)? - person Paul Bormans; 23.06.2017
comment
Bu men uchun ishlaydi!. Bu menga kerak bo'lgan narsa edi. Men shunchaki xatti-harakatlar stsenariysi ob'ektini chop qilmoqchi edim. - person matabares; 26.05.2020
comment
Bu ajoyib yechim. Json moduli uchun murakkab JSON dekoder kengaytmasini yaratish o'rniga men o'z sinfimni bitta qator bilan seriyalashtira oldim: s=jsonpickle.encode(self). Qayta tiklash hamma narsa kabi oddiy edi. Bu haqiqiy Python ruhi. +1 - person NoCake; 18.09.2020

Ko'pgina javoblar qo'ng'iroqni json.dumps() ga o'zgartirishni o'z ichiga oladi, bu har doim ham mumkin emas yoki istalmagan (masalan, ramka komponentida sodir bo'lishi mumkin).

Agar siz json.dumps(obj) ni avvalgidek chaqirishni istasangiz, oddiy yechim dictdan meros qilib olinadi:

class FileItem(dict):
    def __init__(self, fname):
        dict.__init__(self, fname=fname)

f = FileItem('tasks.txt')
json.dumps(f)  #No need to change anything here

Bu sizning sinfingiz oddiy ma'lumotlarni taqdim etish bo'lsa ishlaydi, qiyinroq narsalar uchun kalitlarni har doim aniq belgilashingiz mumkin.

person andyhasit    schedule 03.07.2015
comment
Bu, albatta, yaxshi yechim bo'lishi mumkin :) Men o'z ishimga ishonaman. Afzalliklari: ob'ektni init bilan sinfga aylantirish orqali uning shakli haqida ma'lumot berasiz, u tabiatan seriyali va repr sifatida talqin qilinishi mumkin. - person PascalVKooten; 22.09.2016
comment
Nuqtaga kirish hali ham mavjud emas :( - person PascalVKooten; 22.09.2016
comment
Oh, bu ishlayotganga o'xshaydi! Rahmat, nima uchun bu qabul qilingan javob emasligiga ishonchim komil emas. Men dumps ni o'zgartirish yaxshi yechim emasligiga to'liq qo'shilaman. Aytgancha, ko'p hollarda siz delegatsiya bilan birga dict merosga ega bo'lishni xohlaysiz, bu sizning sinfingiz ichida dict tipidagi atributga ega bo'lishingizni anglatadi, keyin siz ushbu atributni super().__init__(self.elements) kabi ishga tushirish parametri sifatida o'tkazasiz. - person cglacet; 24.08.2018
comment
Foydalanish holatimda json.dumps() ga ko'rinmaydigan ma'lumotlarni saqlashim kerak edi, shuning uchun men ushbu usuldan foydalandim. DictWithRider klassi ixtiyoriy ob'ektni qabul qiladi, uni a'zo sifatida saqlaydi va get_rider_obj() funksiyasi orqali kirish imkonini beradi, lekin uni dict.__init__() ga o'tkazmaydi. Yashirin ma'lumotlarni ko'rmoqchi bo'lgan ilova qismlari d.get_rider_obj() ga qo'ng'iroq qilishlari mumkin, lekin json.dumps() asosan bo'sh dictni ko'radi. @PascalVKooten ta'kidlaganidek, siz nuqta belgisi bilan oddiy a'zolarga kira olmaysiz, lekin funksiyalarga kirishingiz mumkin. - person gkimsey; 21.07.2020
comment
oddiy foydalanish uchun bu ideal. dict.__init__( qatordan keyingi qo'shimcha satrlar orqali nuqta belgilarini self.fname = fname sifatida osongina yoqish mumkin va ob'ektni f = FileItem(**json.loads(serialised_f)) bilan seriyadan chiqarish mumkin. - person paddyg; 21.01.2021
comment
Men buni soddaligi uchun juda yaxshi ko'raman. Siz o'z sinflaringizni to'liq loyihalashingiz kerak (maymun-patching yo'q), lekin sizning sinf a'zolaringiz ob'ektlar ro'yxati bo'lsa ham, u juda yaxshi ishlaydi. - person Cerno; 03.05.2021
comment
6 yil o'tib, bu hali ham eng yaxshi javob - person rossco; 09.07.2021
comment
Aynan shu narsa menga kerak, katta rahmat - person Qingyi Wu; 19.07.2021

Menga Onurning javobi yoqadi, lekin ob'ektlarni ketma-ketlashtirish uchun ixtiyoriy toJSON() usulini qo'shish uchun kengaytiraman:

def dumper(obj):
    try:
        return obj.toJSON()
    except:
        return obj.__dict__
print json.dumps(some_big_object, default=dumper, indent=2)
person Jason S    schedule 27.01.2015
comment
Men buni mavjud json.dumps dan foydalanish va maxsus ishlov berishni joriy qilish o'rtasidagi eng yaxshi muvozanat deb topdim. Rahmat! - person Daniel Buckmaster; 15.04.2015
comment
Menga bu juda yoqadi; lekin try-catch o'rniga, ehtimol, if 'toJSON' in obj.__attrs__():... kabi bir ishni qilsa, jimgina nosozlikni oldini olish uchun (toJSON() da mavjud bo'lmaganidan boshqa sabablarga ko'ra muvaffaqiyatsizlikka uchragan taqdirda) ... ma'lumotlarning buzilishiga olib keladigan nosozlik. - person thclark; 22.11.2017
comment
@thclark, men tushunganimdek, idomatic python kechirim so'raydi, ruxsat emas, shuning uchun try-except to'g'ri yondashuv, lekin to'g'ri istisno tutilishi kerak, bu holda AttributeError. - person Phil; 08.09.2020
comment
@phil bir necha yosh katta va donoroq, men siz bilan rozi bo'lardim. - person thclark; 08.09.2020
comment
Bu, albatta, AttributeError ni aniq tutishi kerak - person juanpa.arrivillaga; 04.02.2021
comment
Va agar AttributeError obj.toJSON() ichida ko'tarilsa nima bo'ladi? - person artm; 16.05.2021

Shunchaki sinfingizga to_json usulini qo'shing:

def to_json(self):
  return self.message # or how you want it to be serialized

Va ushbu kodni (ushbu javobdan), hamma narsaning yuqori qismidagi biror joyga qo'shing:

from json import JSONEncoder

def _default(self, obj):
    return getattr(obj.__class__, "to_json", _default.default)(obj)

_default.default = JSONEncoder().default
JSONEncoder.default = _default

Bu import qilinganida json moduliga maymun-patch qo'yadi, shuning uchun JSONEncoder.default() avtomatik ravishda maxsus "to_json()" usulini tekshiradi va agar topilsa, undan ob'ektni kodlash uchun foydalanadi.

Xuddi Onur aytganidek, lekin bu safar loyihangizdagi har json.dumps() ni yangilashingiz shart emas.

person Fancy John    schedule 04.08.2016
comment
Katta rahmat! Bu menga xohlagan narsani qilishimga imkon beradigan yagona javob: mavjud kodni o'zgartirmasdan ob'ektni seriyalashtira olish. Boshqa usullar asosan men uchun ishlamaydi. Ob'ekt uchinchi tomon kutubxonasida aniqlangan va ketma-ketlashtirish kodi ham uchinchi tomon hisoblanadi. Ularni o'zgartirish noqulay bo'ladi. Sizning usulingiz bilan men faqat TheObject.to_json = my_serializer ni bajarishim kerak. - person Yongwei Wu; 11.10.2017

Yana bir variant - JSON dampingini o'z sinfiga o'rash:

import json

class FileItem:
    def __init__(self, fname):
        self.fname = fname

    def __repr__(self):
        return json.dumps(self.__dict__)

Yoki undan ham yaxshisi, JsonSerializable sinfidagi FileItem sinfining pastki sinfini:

import json

class JsonSerializable(object):
    def toJson(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return self.toJson()


class FileItem(JsonSerializable):
    def __init__(self, fname):
        self.fname = fname

Sinov:

>>> f = FileItem('/foo/bar')
>>> f.toJson()
'{"fname": "/foo/bar"}'
>>> f
'{"fname": "/foo/bar"}'
>>> str(f) # string coercion
'{"fname": "/foo/bar"}'
person Paulo Freitas    schedule 16.06.2012
comment
Salom, menga ushbu maxsus kodlovchi yondashuv yoqmaydi, agar siz o'z sinfingizni json seriyali qilib qo'ysangiz yaxshi bo'lardi. Men harakat qilaman, harakat qilaman va harakat qilaman va hech narsa yo'q. Buni qanday qilish haqida biron bir fikr bormi. Gap shundaki, json moduli sizning sinfingizni o'rnatilgan python turlariga qarshi sinab ko'radi va hatto maxsus sinflar uchun kodlovchingizni yarating :). Soxta bo'lishi mumkinmi? Shunday qilib, men sinfimga biror narsa qila olaman, shuning uchun u json moduliga oddiy ro'yxat kabi harakat qiladimi? Men subclasscheck va instancecheckni sinab ko'raman, lekin hech narsa yo'q. - person Bojan Radojevic; 15.08.2012
comment
@ADRENALIN Agar barcha sinf atributlari qiymatlari ketma-ketlashtirilsa va buzg'unchilikka qarshi bo'lmasangiz, siz asosiy turdan (ehtimol dict) meros olishingiz mumkin. Bundan tashqari, standart o'rniga jsonpickle yoki json_tricks yoki boshqa narsalarni ishlatishingiz mumkin (hali ham maxsus kodlovchi, lekin yozishingiz yoki qo'ng'iroq qilishingiz kerak emas). Birinchisi misolni tuzlaydi, ikkinchisi uni __json__encode__ / __json_decode__ ni amalga oshirish orqali o'zgartirishingiz mumkin bo'lgan atributlar dikti sifatida saqlaydi (oshkor qilish: oxirgisini men qildim). - person Mark; 20.10.2016
comment
Bu json sinfi uchun ob'ektni seriyali qilib qo'ymaydi. U faqat json satrini qaytarish usulini taqdim etadi (arzimas). Shunday qilib, json.dumps(f) muvaffaqiyatsiz bo'ladi. Bu so'ralgan narsa emas. - person omni; 21.09.2020

Boshqa ko'plab javoblarda aytib o'tilganidek, sukut bo'yicha qo'llab-quvvatlanadigan turlardan biri bo'lmagan ob'ektlarni qo'llab-quvvatlanadigan turga aylantirish uchun funksiyani json.dumps ga o'tkazishingiz mumkin. Ajablanarlisi shundaki, ularning hech birida eng oddiy holat, ya'ni o'rnatilgan funksiyasidan foydalanish haqida aytilmagan. vars ob'ektlarni barcha atributlarini o'z ichiga olgan dictga aylantirish uchun:

json.dumps(obj, default=vars)

E'tibor bering, bu faqat asosiy holatlarni qamrab oladi, agar sizga ma'lum turlar uchun (masalan, ma'lum atributlar bundan mustasno yoki __dict__ atributiga ega bo'lmagan ob'ektlar uchun) aniqroq ketma-ketlashtirish kerak bo'lsa, boshqa javoblarda aytilganidek, maxsus funksiya yoki JSONEncoder dan foydalanishingiz kerak. .

person user1587520    schedule 21.10.2020
comment
default=vars bilan nimani nazarda tutayotganingiz tushunarsiz, bu vars standart serializator ekanligini anglatadimi? Agar shunday bo'lmasa: Bu json.dumps qanday chaqirilishiga ta'sir qila olmaydigan holatni hal qilmaydi. Agar siz shunchaki ob'ektni kutubxonaga o'tkazsangiz va kutubxona ushbu ob'ektga json.dumps qo'ng'iroq qilsa, bu kutubxona dumps dan bu tarzda foydalanmasa, vars ni amalga oshirganingizga yordam bermaydi. Shu ma'noda u odatiy JSONEncoder ga teng. - person Felix B.; 24.11.2020
comment
Siz to'g'risiz, bu maxsus serializator uchun oddiy tanlovdan boshqa narsa emas va siz tasvirlagan ishni hal qilmaydi. Agar men buni to'g'ri ko'rsam, json.dumps qanday chaqirilishini nazorat qilmasangiz, masalaning yechimi yo'q. - person user1587520; 25.11.2020
comment
Mening ishimni hal qildim. Shunchaki ajoyib! - person Rub; 02.12.2020
comment
Ba'zi ob'ektlar uchun bu yondashuv vars() argument must have __dict__ attribute ni tashlaydi - person JustAMartin; 24.02.2021

Men boshqa kuni bu muammoga duch keldim va Python ob'ektlari uchun kodlovchining umumiy versiyasini joriy qildim, u ichiga o'rnatilgan ob'ektlar va meroslangan maydonlarni boshqarishi mumkin:

import json
import inspect

class ObjectEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, "to_json"):
            return self.default(obj.to_json())
        elif hasattr(obj, "__dict__"):
            d = dict(
                (key, value)
                for key, value in inspect.getmembers(obj)
                if not key.startswith("__")
                and not inspect.isabstract(value)
                and not inspect.isbuiltin(value)
                and not inspect.isfunction(value)
                and not inspect.isgenerator(value)
                and not inspect.isgeneratorfunction(value)
                and not inspect.ismethod(value)
                and not inspect.ismethoddescriptor(value)
                and not inspect.isroutine(value)
            )
            return self.default(d)
        return obj

Misol:

class C(object):
    c = "NO"
    def to_json(self):
        return {"c": "YES"}

class B(object):
    b = "B"
    i = "I"
    def __init__(self, y):
        self.y = y
        
    def f(self):
        print "f"

class A(B):
    a = "A"
    def __init__(self):
        self.b = [{"ab": B("y")}]
        self.c = C()

print json.dumps(A(), cls=ObjectEncoder, indent=2, sort_keys=True)

Natija:

{
  "a": "A", 
  "b": [
    {
      "ab": {
        "b": "B", 
        "i": "I", 
        "y": "y"
      }
    }
  ], 
  "c": {
    "c": "YES"
  }, 
  "i": "I"
}
person tobigue    schedule 18.02.2016
comment
Garchi bu biroz eski bo'lsa-da..Men ba'zi dumaloq import xatosiga duch keldim. Shunday qilib, oxirgi qatordagi return obj o'rniga men buni return super(ObjectEncoder, self).default(obj) qildim. Malumot SHU YERDA - person SomeTypeFoo; 11.04.2017

Agar siz Python3.5+ dan foydalansangiz, jsons dan foydalanishingiz mumkin. (PyPi: https://pypi.org/project/jsons/) U ob'ektingizni aylantiradi. (va uning barcha atributlari rekursiv) dictga.

import jsons

a_dict = jsons.dump(your_object)

Yoki qatorni xohlasangiz:

a_str = jsons.dumps(your_object)

Yoki sizning sinfingiz jsons.JsonSerializable ni amalga oshirgan bo'lsa:

a_dict = your_object.json
person R H    schedule 19.12.2018
comment
Agar siz Python 3.7+ dan foydalana olsangiz, men python sinflarini dicts va JSON satrlariga (va aksincha) aylantirishning eng toza yechimi jsons kutubxonasini ma'lumotlar sinflari. Hozircha, men uchun juda yaxshi! - person Ruluk; 26.02.2019
comment
Bu standart Python o'rnatilishiga o'rnatilmagan tashqi kutubxona. - person Noumenon; 10.07.2019
comment
faqat slots atributiga ega sinf uchun - person yehudahs; 03.12.2019
comment
Mumkin, lekin slotlardan foydalanish shart emas. Faqat ma'lum bir sinfning imzosi bo'yicha damping paytida sizga slotlar kerak bo'ladi. Kelgusi 1.1.0 versiyasida ham endi bunday bo'lmaydi. - person R H; 04.12.2019

import simplejson

class User(object):
    def __init__(self, name, mail):
        self.name = name
        self.mail = mail

    def _asdict(self):
        return self.__dict__

print(simplejson.dumps(User('alice', '[email protected]')))

standart json dan foydalansangiz, default funksiyasini belgilashingiz kerak

import json
def default(o):
    return o._asdict()

print(json.dumps(User('alice', '[email protected]'), default=default))
person tryer3000    schedule 17.06.2015
comment
Men _asdict funksiyasini lambda json.dumps(User('alice', '[email protected]'), default=lambda x: x.__dict__) bilan olib tashlash orqali buni soddalashtirdim. - person JustEngland; 29.11.2018

json chop etishi mumkin bo'lgan ob'ektlar nuqtai nazaridan cheklangan va jsonpickle (sizga pip install jsonpickle kerak bo'lishi mumkin) matnni cheklamasligi bilan cheklangan. Agar siz sinfini o'zgartira olmaydigan ob'ektning mazmunini tekshirmoqchi bo'lsangiz, men hali ham to'g'riroq yo'l topa olmadim:

 import json
 import jsonpickle
 ...
 print  json.dumps(json.loads(jsonpickle.encode(object)), indent=2)

Eslatma: ular hali ham ob'ekt usullarini chop eta olmaydilar.

person ribamar    schedule 04.04.2016

Bu sinf hiyla qila oladi, ob'ektni standart json ga o'zgartiradi.

import json


class Serializer(object):
    @staticmethod
    def serialize(object):
        return json.dumps(object, default=lambda o: o.__dict__.values()[0])

foydalanish:

Serializer.serialize(my_object)

python2.7 va python3 da ishlash.

person Lost Koder    schedule 09.10.2016
comment
Menga bu usul eng yoqdi. A'zolari/usullari seriyali bo'lmagan murakkabroq ob'ektlarni ketma-ketlashtirishga urinayotganda muammolarga duch keldim. Mana mening ko‘proq obyektlarda ishlaydigan ilovam: ``` sinf Serializer(ob'ekt): @staticmethod def serialize(obj): def check(o): k, v in o.__dict__.items(): urinib ko'ring: _ = json .dumps(v) o.__dict__[k] = v TypeErrordan tashqari: o.__dict__[k] = str(v) qaytish yoki json.dumps(check(obj).__dict__, indent=2) ``` - person Will Charlton; 11.11.2017

Mana mening 3 sentim...
Bu daraxtga o'xshash python ob'ekti uchun aniq json serializatsiyasini ko'rsatadi.
Eslatma: Agar siz haqiqatan ham shunday kodni xohlasangiz, twisted FilePath sinfi.

import json, sys, os

class File:
    def __init__(self, path):
        self.path = path

    def isdir(self):
        return os.path.isdir(self.path)

    def isfile(self):
        return os.path.isfile(self.path)

    def children(self):        
        return [File(os.path.join(self.path, f)) 
                for f in os.listdir(self.path)]

    def getsize(self):        
        return os.path.getsize(self.path)

    def getModificationTime(self):
        return os.path.getmtime(self.path)

def _default(o):
    d = {}
    d['path'] = o.path
    d['isFile'] = o.isfile()
    d['isDir'] = o.isdir()
    d['mtime'] = int(o.getModificationTime())
    d['size'] = o.getsize() if o.isfile() else 0
    if o.isdir(): d['children'] = o.children()
    return d

folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)
person Dan Brough    schedule 10.07.2013

jaraco juda aniq javob berdi. Men ba'zi kichik narsalarni tuzatishim kerak edi, lekin bu ishlaydi:

Kod

# Your custom class
class MyCustom(object):
    def __json__(self):
        return {
            'a': self.a,
            'b': self.b,
            '__python__': 'mymodule.submodule:MyCustom.from_json',
        }

    to_json = __json__  # supported by simplejson

    @classmethod
    def from_json(cls, json):
        obj = cls()
        obj.a = json['a']
        obj.b = json['b']
        return obj

# Dumping and loading
import simplejson

obj = MyCustom()
obj.a = 3
obj.b = 4

json = simplejson.dumps(obj, for_json=True)

# Two-step loading
obj2_dict = simplejson.loads(json)
obj2 = MyCustom.from_json(obj2_dict)

# Make sure we have the correct thing
assert isinstance(obj2, MyCustom)
assert obj2.__dict__ == obj.__dict__

E'tibor bering, yuklash uchun bizga ikkita qadam kerak. Hozircha __python__ xususiyati ishlatilmaydi.

Bu qanchalik keng tarqalgan?

AlJohri usulidan foydalanib, yondashuvlarning mashhurligini tekshiraman:

Seriyalashtirish (Python -> JSON):

Deserializatsiya (JSON -> Python):

person Martin Thoma    schedule 27.06.2018

Bu men uchun yaxshi ishladi:

class JsonSerializable(object):

    def serialize(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return self.serialize()

    @staticmethod
    def dumper(obj):
        if "serialize" in dir(obj):
            return obj.serialize()

        return obj.__dict__

undan keyin

class FileItem(JsonSerializable):
    ...

va

log.debug(json.dumps(<my object>, default=JsonSerializable.dumper, indent=2))
person jmhostalet    schedule 18.01.2019

Agar paketni oʻrnatishga qarshi boʻlmasangiz, json-tricks:

pip install json-tricks

Shundan so'ng siz json o'rniga json_tricks dan dump(s) ni import qilishingiz kerak va u odatda ishlaydi:

from json_tricks import dumps
json_str = dumps(cls_instance, indent=4)

qaysi beradi

{
        "__instance_type__": [
                "module_name.test_class",
                "MyTestCls"
        ],
        "attributes": {
                "attr": "val",
                "dct_attr": {
                        "hello": 42
                }
        }
}

Va bu, asosan, shunday!


Bu umuman olganda ajoyib ishlaydi. Ba'zi istisnolar mavjud, masalan. agar __new__ da maxsus narsalar sodir bo'lsa yoki ko'proq metaklass sehrlari davom etsa.

Shubhasiz, yuklash ham ishlaydi (aks holda nima bo'ladi):

from json_tricks import loads
json_str = loads(json_str)

Bu module_name.test_class.MyTestCls import qilinishi mumkinligini va mos kelmaydigan usullarda o'zgarmasligini nazarda tutadi. Siz lug'at yoki boshqa narsalarni emas, balki namunani qaytarasiz va u siz tashlagan nusxaning bir xil nusxasi bo'lishi kerak.

Agar biror narsaning seriyali bo'lishini sozlashni istasangiz, sinfingizga maxsus usullarni qo'shishingiz mumkin, masalan:

class CustomEncodeCls:
        def __init__(self):
                self.relevant = 42
                self.irrelevant = 37

        def __json_encode__(self):
                # should return primitive, serializable types like dict, list, int, string, float...
                return {'relevant': self.relevant}

        def __json_decode__(self, **attrs):
                # should initialize all properties; note that __init__ is not called implicitly
                self.relevant = attrs['relevant']
                self.irrelevant = 12

misol sifatida atributlar parametrlarining faqat bir qismini ketma-ketlashtiradi.

Va bepul bonus sifatida siz numpy massivlarni, sana va vaqtlarni, buyurtma qilingan xaritalarni seriyalashtirishni, shuningdek json-ga sharhlarni kiritish imkoniyatini olasiz.

Rad etish: Men json_tricks ni yaratdim, chunki menda siz bilan bir xil muammo bor edi.

person Mark    schedule 10.11.2016
comment
Men hozirgina json_tricksni sinab ko'rdim va u beautify ishladi (2019 yilda). - person pauljohn32; 06.11.2019

Kyle Delaneyning izohi to‘g‘ri shuning uchun men https://stackoverflow.com, shuningdek https://stackoverflow.com/a/10254820/1497139takomillashtirilganversiyasi.

JSONAble mixini yaratish uchun.

Shunday qilib, JSON sinfini seriyali qilish uchun super sinf sifatida JSONAble dan foydalaning va qo'ng'iroq qiling:

 instance.toJSON()

or

 instance.asJSON()

taklif qilingan ikkita usul uchun. JSONAble sinfini bu yerda taklif qilingan boshqa yondashuvlar bilan ham kengaytirishingiz mumkin.

Oila va shaxs bilan birlik testi namunasi uchun test namunasi quyidagi natijalarni beradi:

toJSON():

{
    "members": {
        "Flintstone,Fred": {
            "firstName": "Fred",
            "lastName": "Flintstone"
        },
        "Flintstone,Wilma": {
            "firstName": "Wilma",
            "lastName": "Flintstone"
        }
    },
    "name": "The Flintstones"
}

asJSON():

{'name': 'The Flintstones', 'members': {'Flintstone,Fred': {'firstName': 'Fred', 'lastName': 'Flintstone'}, 'Flintstone,Wilma': {'firstName': 'Wilma', 'lastName': 'Flintstone'}}}

Oila va shaxs bilan birlik testi namunasi

def testJsonAble(self):
        family=Family("The Flintstones")
        family.add(Person("Fred","Flintstone")) 
        family.add(Person("Wilma","Flintstone"))
        json1=family.toJSON()
        json2=family.asJSON()
        print(json1)
        print(json2)

class Family(JSONAble):
    def __init__(self,name):
        self.name=name
        self.members={}
    
    def add(self,person):
        self.members[person.lastName+","+person.firstName]=person

class Person(JSONAble):
    def __init__(self,firstName,lastName):
        self.firstName=firstName;
        self.lastName=lastName;

jsonable.py JSONAble aralashmasini aniqlaydi

 '''
Created on 2020-09-03

@author: wf
'''
import json

class JSONAble(object):
    '''
    mixin to allow classes to be JSON serializable see
    https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable
    '''

    def __init__(self):
        '''
        Constructor
        '''
    
    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, 
            sort_keys=True, indent=4)
        
    def getValue(self,v):
        if (hasattr(v, "asJSON")):
            return v.asJSON()
        elif type(v) is dict:
            return self.reprDict(v)
        elif type(v) is list:
            vlist=[]
            for vitem in v:
                vlist.append(self.getValue(vitem))
            return vlist
        else:   
            return v
    
    def reprDict(self,srcDict):
        '''
        get my dict elements
        '''
        d = dict()
        for a, v in srcDict.items():
            d[a]=self.getValue(v)
        return d
    
    def asJSON(self):
        '''
        recursively return my dict elements
        '''
        return self.reprDict(self.__dict__)   

Ushbu yondashuvlarni endi https://github.com/WolfgangFahl/pyLoDStorage loyihasida integratsiyalashgan holda topasiz. Bu https://pypi.org/project/pylodstorage/ sahifasida mavjud

person Wolfgang Fahl    schedule 03.09.2020

jsonweb men uchun eng yaxshi yechim kabi ko'rinadi. http://www.jsonweb.info/en/latest/ ga qarang.

from jsonweb.encode import to_object, dumper

@to_object()
class DataModel(object):
  def __init__(self, id, value):
   self.id = id
   self.value = value

>>> data = DataModel(5, "foo")
>>> dumper(data)
'{"__type__": "DataModel", "id": 5, "value": "foo"}'
person matthewlent    schedule 07.10.2014
comment
U o'rnatilgan ob'ektlar uchun yaxshi ishlaydimi? Shu jumladan dekodlash va kodlash - person Simone Zandara; 22.12.2015

Quinten Cabo asosida qurish javob:

def sterilize(obj):
    """Make an object more ameniable to dumping as json
    """
    if type(obj) in (str, float, int, bool, type(None)):
        return obj
    elif isinstance(obj, dict):
        return {k: sterilize(v) for k, v in obj.items()}
    list_ret = []
    dict_ret = {}
    for a in dir(obj):
        if a == '__iter__' and callable(obj.__iter__):
            list_ret.extend([sterilize(v) for v in obj])
        elif a == '__dict__':
            dict_ret.update({k: sterilize(v) for k, v in obj.__dict__.items() if k not in ['__module__', '__dict__', '__weakref__', '__doc__']})
        elif a not in ['__doc__', '__module__']:
            aval = getattr(obj, a)
            if type(aval) in (str, float, int, bool, type(None)):
                dict_ret[a] = aval
            elif a != '__class__' and a != '__objclass__' and isinstance(aval, type):
                dict_ret[a] = sterilize(aval)
    if len(list_ret) == 0:
        if len(dict_ret) == 0:
            return repr(obj)
        return dict_ret
    else:
        if len(dict_ret) == 0:
            return list_ret
    return (list_ret, dict_ret)

Farqlar

  1. Faqat list va tuple o'rniga har qanday iteratsiya uchun ishlaydi (u NumPy massivlari va boshqalar uchun ishlaydi).
  2. Dinamik turlar uchun ishlaydi (__dict__ ni o'z ichiga olganlar).
  3. float va None mahalliy turlarini o'z ichiga oladi, shuning uchun ular stringga aylantirilmaydi.
  4. __dict__ va aʼzolar boʻlgan sinflar asosan ishlaydi (agar __dict__ va aʼzo nomlari toʻqnash kelsa, siz faqat bittasini olasiz – ehtimol aʼzo)
  5. Roʻyxat boʻlgan va aʼzolari boʻlgan sinflar roʻyxat va lugʻat toʻplamiga oʻxshaydi
  6. Python3 (bu isinstance() qo'ng'irog'i o'zgartirilishi kerak bo'lgan yagona narsa bo'lishi mumkin)
person mheyman    schedule 02.05.2020

Menga Lost Koderning usuli eng yoqdi. A'zolari/usullari seriyali bo'lmagan murakkabroq ob'ektlarni ketma-ketlashtirishga urinayotganda muammolarga duch keldim. Ko'proq ob'ektlarda ishlaydigan mening ilovam:

class Serializer(object):
    @staticmethod
    def serialize(obj):
        def check(o):
            for k, v in o.__dict__.items():
                try:
                    _ = json.dumps(v)
                    o.__dict__[k] = v
                except TypeError:
                    o.__dict__[k] = str(v)
            return o
        return json.dumps(check(obj).__dict__, indent=2)
person Will Charlton    schedule 11.11.2017

Peewee modelini PostgreSQL JSONField da saqlashga harakat qilganimda bu muammoga duch keldim.

Biroz kurashgandan so'ng, umumiy yechim.

Mening yechimimning kaliti Python-ning manba kodidan o'tish va kod hujjatlari (ta'riflangan bu yerda) boshqa ma'lumotlar turlarini qo'llab-quvvatlash uchun mavjud json.dumps ni qanday kengaytirishni allaqachon tushuntirib beradi.

Aytaylik, sizda JSON uchun ketma-ketlashtirib bo'lmaydigan ba'zi maydonlarni o'z ichiga olgan model mavjud va JSON maydonini o'z ichiga olgan model dastlab shunday ko'rinadi:

class SomeClass(Model):
    json_field = JSONField()

Shunchaki maxsus JSONEncoder belgilang:

class CustomJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, SomeTypeUnsupportedByJsonDumps):
            return < whatever value you want >
        return json.JSONEncoder.default(self, obj)

    @staticmethod
    def json_dumper(obj):
        return json.dumps(obj, cls=CustomJsonEncoder)

Va keyin uni quyidagi kabi JSONField da foydalaning:

class SomeClass(Model):
    json_field = JSONField(dumps=CustomJsonEncoder.json_dumper)

Kalit yuqoridagi default(self, obj) usulidir. Python’dan kelgan har bir ... is not JSON serializable shikoyat uchun seriyali bo‘lmagan JSON turiga (masalan, Enum yoki datetime) ishlov berish uchun kod qo‘shing.

Misol uchun, men Enum dan meros bo'lgan sinfni qanday qo'llab-quvvatlayman:

class TransactionType(Enum):
   CURRENT = 1
   STACKED = 2

   def default(self, obj):
       if isinstance(obj, TransactionType):
           return obj.value
       return json.JSONEncoder.default(self, obj)

Nihoyat, yuqoridagi kabi amalga oshirilgan kod bilan siz har qanday Peewee modellarini quyidagi kabi JSON-seriyali ob'ektga aylantirishingiz mumkin:

peewee_model = WhateverPeeweeModel()
new_model = SomeClass()
new_model.json_field = model_to_dict(peewee_model)

Yuqoridagi kod (bir oz) Peewee-ga xos bo'lsa-da, lekin menimcha:

  1. Bu umuman boshqa ORM (Django va boshqalar) uchun amal qiladi
  2. Bundan tashqari, agar siz json.dumps qanday ishlashini tushunsangiz, bu yechim umuman Python (sans ORM) bilan ham ishlaydi.

Har qanday savol, iltimos, sharhlar bo'limiga yozing. Rahmat!

person sivabudh    schedule 30.07.2018

Avval biz ob'ektimizni JSONga moslashimiz kerak, shuning uchun uni standart JSON moduli yordamida o'chirib tashlashimiz mumkin. Men buni shunday qildim:

def serialize(o):
    if isinstance(o, dict):
        return {k:serialize(v) for k,v in o.items()}
    if isinstance(o, list):
        return [serialize(e) for e in o]
    if isinstance(o, bytes):
        return o.decode("utf-8")
    return o
person Adi Degani    schedule 27.02.2020

Bu funktsiya lug'atning har bir qismini takrorlash uchun rekursiyadan foydalanadi va keyin o'rnatilgan turdagi bo'lmagan sinflarning repr() usullarini chaqiradi.

def sterilize(obj):
    object_type = type(obj)
    if isinstance(obj, dict):
        return {k: sterilize(v) for k, v in obj.items()}
    elif object_type in (list, tuple):
        return [sterilize(v) for v in obj]
    elif object_type in (str, int, bool, float):
        return obj
    else:
        return obj.__repr__()
person Quinten Cabo    schedule 30.03.2020

Men o'zimning yechimim bilan keldim. Ushbu usuldan foydalaning, ketma-ketlashtirish uchun istalgan hujjatni (dict,list, ObjectId va hokazo) o'tkazing.

def getSerializable(doc):
    # check if it's a list
    if isinstance(doc, list):
        for i, val in enumerate(doc):
            doc[i] = getSerializable(doc[i])
        return doc

    # check if it's a dict
    if isinstance(doc, dict):
        for key in doc.keys():
            doc[key] = getSerializable(doc[key])
        return doc

    # Process ObjectId
    if isinstance(doc, ObjectId):
        doc = str(doc)
        return doc

    # Use any other custom serializting stuff here...

    # For the rest of stuff
    return doc
person Dewsworld    schedule 21.05.2015

Agar siz paketni o'rnatish imkoniga ega bo'lsangiz, dereotuni sinab ko'rishni tavsiya qilaman, bu juda yaxshi ishladi. mening loyiham. Ushbu paketning yoqimli tomoni shundaki, u pickle bilan bir xil interfeysga ega, shuning uchun agar siz allaqachon loyihangizda pickle dan foydalanayotgan bo'lsangiz, shunchaki dill ni almashtirib, hech qanday kodni o'zgartirmasdan skript ishlayotganligini ko'rishingiz mumkin. Shunday qilib, sinash uchun juda arzon echim!

(To'liq oshkor etilishiga qarshi: men hech qanday tarzda arpabodiyon loyihasiga aloqador emasman va hech qachon hissa qo'shganim yo'q.)

Paketni o'rnating:

pip install dill

Keyin pickle oʻrniga dill import qilish uchun kodingizni tahrirlang:

# import pickle
import dill as pickle

Skriptingizni ishga tushiring va u ishlayotganligini tekshiring. (Agar shunday bo'lsa, pickle modul nomini soya qilmaslik uchun kodingizni tozalashni xohlashingiz mumkin!)

loyiha sahifasidan dill seriyalashtira oladigan va seriyalashtira olmaydigan ma'lumotlar turlariga oid ba'zi xususiyatlar:

dill quyidagi standart turlarni tuzlashi mumkin:

none, type, bool, int, long, float, kompleks, str, unicode, kortej, roʻyxat, dict, fayl, bufer, oʻrnatilgan, eski va yangi uslub sinflari, eski va yangi uslublar sinflari, toʻsiq, frozenset, massiv , funksiyalar, istisnolar

dill ko'proq "ekzotik" standart turlarni ham tanlashi mumkin:

unumli funksiyalar, ichki funksiyalar, lambdalar, katakchalar, usul, unboundmethod, modul, code, methodwrapper, dictproxy, methoddescriptor, getsetdescriptor, memberdescriptor, wrapperdescriptor, xrange, slice, notimplemented, ellipsis, quit

dill hali bu standart turlarni tanlay olmaydi:

ramka, generator, orqaga qaytish

person thedavidmo    schedule 18.12.2018

Men bu erda ketma-ket versiya yoki orqa kompat haqida hech qanday eslatma ko'rmayapman, shuning uchun men birozdan beri foydalanayotgan yechimimni e'lon qilaman. Ehtimol, menda ko'p narsalarni o'rganishim mumkin, xususan, Java va Javascript bu erda mendan ko'ra etukroqdir, lekin bu erda

https://gist.github.com/andy-d/b7878d0044a4280d


Boshqa variantni qo'shish uchun: attrs paketi va asdict usulidan foydalanishingiz mumkin.

class ObjectEncoder(JSONEncoder):
    def default(self, o):
        return attr.asdict(o)

json.dumps(objects, cls=ObjectEncoder)

va orqaga aylantirish uchun

def from_json(o):
    if '_obj_name' in o:
        type_ = o['_obj_name']
        del o['_obj_name']
        return globals()[type_](**o)
    else:
        return o

data = JSONDecoder(object_hook=from_json).decode(data)

sinf shunday ko'rinadi

@attr.s
class Foo(object):
    x = attr.ib()
    _obj_name = attr.ib(init=False, default='Foo')
person machinekoder    schedule 15.10.2019

Onurning javobiga qo'shimcha ravishda, siz quyida bo'lgani kabi datetime turi bilan shug'ullanishni xohlashingiz mumkin.
(ishlash uchun). : 'datetime.datetime' ob'ektida "dict" atributi istisnolari yo'q.)

def datetime_option(value):
    if isinstance(value, datetime.date):
        return value.timestamp()
    else:
        return value.__dict__

Foydalanish:

def toJSON(self):
    return json.dumps(self, default=datetime_option, sort_keys=True, indent=4)
person Mark Choi    schedule 03.02.2020

Bu kichik kutubxona bo'lib, u ob'ektni barcha bolalari bilan JSONga seriyalashtiradi va uni qayta tahlil qiladi:

https://github.com/tobiasholler/PyJSONSerialization/

person Tobi    schedule 17.07.2014

Ushbu muammoga ko'plab yondashuvlar mavjud. "ObjDict" (pip o'rnatish objdict) boshqa. JSON-dan yuklangan ma'lumotlarni eng yaxshi tarzda qayta ishlash uchun lug'atlar kabi ishlashi mumkin bo'lgan ob'ektlar kabi JavaScript-ni taqdim etishga e'tibor qaratilgan, ammo foydali bo'lishi mumkin bo'lgan boshqa xususiyatlar ham mavjud. Bu asl muammoning boshqa muqobil yechimini taqdim etadi.

person innov8    schedule 02.10.2016

Datetime ob'ektini ketma-ketlashtirish muammosini hal qilish uchun dekoratorlardan foydalanishni tanladim. Mana mening kodim:

#myjson.py
#Author: jmooremcc 7/16/2017

import json
from datetime import datetime, date, time, timedelta
"""
This module uses decorators to serialize date objects using json
The filename is myjson.py
In another module you simply add the following import statement:
    from myjson import json

json.dumps and json.dump will then correctly serialize datetime and date 
objects
"""

def json_serial(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        serial = str(obj)
        return serial
    raise TypeError ("Type %s not serializable" % type(obj))


def FixDumps(fn):
    def hook(obj):
        return fn(obj, default=json_serial)

    return hook

def FixDump(fn):
    def hook(obj, fp):
        return fn(obj,fp, default=json_serial)

    return hook


json.dumps=FixDumps(json.dumps)
json.dump=FixDump(json.dump)


if __name__=="__main__":
    today=datetime.now()
    data={'atime':today, 'greet':'Hello'}
    str=json.dumps(data)
    print str

Yuqoridagi modulni import qilish orqali, mening boshqa modullarim json-dan an'anaviy tarzda (standart kalit so'zni ko'rsatmasdan) sana-vaqt ob'ektlarini o'z ichiga olgan ma'lumotlarni ketma-ketlashtirish uchun foydalanadi. Datetime serializer kodi avtomatik ravishda json.dumps va json.dump uchun chaqiriladi.

person John Moore    schedule 16.07.2017

person    schedule
comment
docdan: default(obj) parametri qaytarilishi kerak bo'lgan funksiyadir. obj ning serializatsiya qilinadigan versiyasi yoki TypeError-ni ko'taring. Standart default oddiygina TypeErrorni oshiradi. - person luckydonald; 28.06.2016