Saya ingin menggunakan Python untuk mengubah data JSON menjadi objek Python.
Saya menerima objek data JSON dari Facebook API, yang ingin saya simpan di basis data saya.
Tampilan saya saat ini di Django (Python) ( request.POST
berisi JSON):
response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()
Ini berfungsi dengan baik, tetapi bagaimana saya menangani objek data JSON yang kompleks?
Bukankah lebih baik jika saya bisa mengubah objek JSON ini menjadi objek Python agar mudah digunakan?
dict
s adalah cara yang lemah untuk melakukan pemrograman berorientasi objek. Kamus adalah cara yang sangat buruk untuk mengomunikasikan harapan kepada pembaca kode Anda. Menggunakan kamus, bagaimana Anda dapat dengan jelas dan dapat digunakan kembali menentukan bahwa beberapa pasangan nilai kunci kamus diperlukan, sementara yang lain tidak? Bagaimana dengan mengonfirmasi bahwa nilai yang diberikan berada dalam kisaran atau set yang dapat diterima? Bagaimana dengan fungsi yang khusus untuk jenis objek yang Anda kerjakan (metode alias)? Kamus sangat berguna dan serbaguna, tetapi terlalu banyak dev bertindak seperti mereka lupa Python adalah bahasa berorientasi objek karena suatu alasan.Jawaban:
Anda dapat melakukannya dalam satu baris, menggunakan
namedtuple
danobject_hook
:atau, untuk menggunakan kembali ini dengan mudah:
Jika Anda ingin menangani kunci yang tidak nama-nama atribut yang baik, check out
namedtuple
'srename
parameter .sumber
d.keys()
dand.values()
mengulangi dalam urutan yang sama tidak dijamin, tetapi saya salah. The docs mengatakan: "Jika kunci, nilai-nilai dan item pandangan yang iterasi berakhir tanpa modifikasi intervensi ke dalam kamus, urutan item akan langsung bersesuaian.". Baik untuk mengetahui blok kode lokal kecil seperti itu. Saya akan menambahkan komentar meskipun untuk secara eksplisit mengingatkan pengelola kode ketergantungan seperti itu.x._asdict()
, yang mungkin membantu untuk kasus-kasus sederhana.Lihat bagian berjudul Mengkhususkan decoding objek JSON dalam
json
dokumentasi modul . Anda bisa menggunakannya untuk mendekode objek JSON menjadi tipe Python tertentu.Ini sebuah contoh:
Memperbarui
Jika Anda ingin mengakses data dalam kamus melalui modul json, lakukan ini:
Sama seperti kamus biasa.
sumber
Ini bukan kode golf, tapi di sini adalah trik terpendek saya, menggunakan
types.SimpleNamespace
sebagai wadah untuk objek JSON.Dibandingkan dengan
namedtuple
solusi terkemuka , itu adalah:rename
opsi, dan mungkin batasan yang sama pada kunci yang bukan pengidentifikasi yang valid (digunakan disetattr
bawah penutup)Contoh:
sumber
@post_load
dekoratornya. marshmallow.readthedocs.io/en/latest/…from types import SimpleNamespace
dan gunakan:x = json.loads(data, object_hook=lambda d: SimpleNamespace(**d))
types.SimpleNamespace
sayangnya, tidak ada di 2.7, sayangnya).print_function
?Anda bisa mencoba ini:
Cukup buat Obyek baru, dan berikan parameter sebagai peta.
sumber
Inilah alternatif acar json yang cepat dan kotor
sumber
Untuk objek yang kompleks, Anda dapat menggunakan JSON Pickle
sumber
jsonstruct originally a fork of jsonpickle (Thanks guys!). The key difference between this library and jsonpickle is that during deserialization, jsonpickle requires Python types to be recorded as part of the JSON. This library intends to remove this requirement, instead, requires a class to be passed in as an argument so that its definition can be inspected. It will then return an instance of the given class. This approach is similar to how Jackson (of Java) works.
'[{"name":"object1"},{"name":"object2"}]'
. jsonpickle juga tidak menanganinya dengan baik.Jika Anda menggunakan Python 3.5+, Anda bisa menggunakan
jsons
untuk membuat serial dan deserialize ke objek Python lama:Anda juga bisa membuat
FbApiUser
warisan darijsons.JsonSerializable
untuk lebih elegan:Contoh-contoh ini akan berfungsi jika kelas Anda terdiri dari tipe standar Python, seperti string, integer, daftar, datetimes, dll.
jsons
Lib akan memerlukan petunjuk tipe untuk tipe kustom.sumber
Jika Anda menggunakan python 3.6+, Anda dapat menggunakan marshmallow-dataclass . Berlawanan dengan semua solusi yang tercantum di atas, ini sederhana, dan mengetik aman:
sumber
TypeError: make_data_class() got an unexpected keyword argument 'many'
Meningkatkan jawaban lovasoa yang sangat bagus.
Jika Anda menggunakan python 3.6+, Anda dapat menggunakan:
pip install marshmallow-enum
danpip install marshmallow-dataclass
Sederhana dan aman.
Anda bisa mengubah kelas Anda dalam string-json dan sebaliknya:
Dari Object ke String Json:
Dari String Json ke Object:
Definisi kelas:
sumber
Saya telah menulis kerangka serialisasi kecil (de) yang disebut any2any yang membantu melakukan transformasi kompleks antara dua jenis Python.
Dalam kasus Anda, saya kira Anda ingin mengubah dari kamus (diperoleh dengan
json.loads
) menjadi objek yang kompleksresponse.education ; response.name
, dengan struktur bersarangresponse.education.id
, dll ... Jadi itulah kerangka yang dibuat untuk ini. Dokumentasi belum bagus, tetapi dengan menggunakanany2any.simple.MappingToObject
, Anda harus dapat melakukannya dengan sangat mudah. Silahkan bertanya jika Anda memerlukan bantuan.sumber
Karena tidak ada yang memberikan jawaban seperti milik saya, saya akan mempostingnya di sini.
Ini adalah kelas yang kuat yang dapat dengan mudah mengkonversi bolak-balik antara json
str
dandict
yang saya salin dari jawaban saya untuk pertanyaan lain :sumber
Mengubah respons @DS sedikit, untuk memuat dari file:
Satu hal: ini tidak dapat memuat item dengan angka di depan. Seperti ini:
Karena "1_first_item" bukan nama bidang python yang valid.
sumber
Saat mencari solusi, saya menemukan posting blog ini: https://blog.mosthege.net/2016/11/12/json-deserialization-of-nested-objects/
Ini menggunakan teknik yang sama seperti yang dinyatakan dalam jawaban sebelumnya tetapi dengan penggunaan dekorator. Hal lain yang saya temukan berguna adalah kenyataan bahwa ia mengembalikan objek yang diketik pada akhir deserialisation
Pemakaian:
sumber
Memperluas jawaban DS sedikit, jika Anda membutuhkan objek agar bisa berubah (yang namesuple tidak), Anda dapat menggunakan perpustakaan recordclass alih-alih namedtuple:
Objek yang dimodifikasi kemudian dapat dikonversi kembali ke json dengan sangat mudah menggunakan simplejson :
sumber
Jika Anda menggunakan Python 3.6 atau yang lebih baru, Anda bisa melihat squema - modul ringan untuk struktur data yang diketik secara statis. Itu membuat kode Anda mudah dibaca sementara pada saat yang sama memberikan validasi data sederhana, konversi dan serialisasi tanpa kerja ekstra. Anda bisa menganggapnya sebagai alternatif yang lebih canggih dan beralasan untuk namtuple dan dataclasses. Inilah cara Anda dapat menggunakannya:
sumber
Saya sedang mencari solusi yang berhasil
recordclass.RecordClass
, mendukung objek bersarang dan bekerja untuk serialisasi json dan deserialisasi json.Memperluas jawaban DS, dan memperluas solusi dari BeneStr, saya menghasilkan hal-hal berikut yang tampaknya berhasil:
Kode:
Pemakaian:
sumber
Jawaban yang diberikan di sini tidak mengembalikan tipe objek yang benar, maka saya membuat metode ini di bawah ini. Mereka juga gagal jika Anda mencoba menambahkan lebih banyak bidang ke kelas yang tidak ada di JSON yang diberikan:
sumber
Python3.x
Pendekatan terbaik yang bisa saya capai dengan pengetahuan saya adalah ini.
Perhatikan bahwa kode ini memperlakukan set () juga.
Pendekatan ini generik hanya membutuhkan ekstensi kelas (dalam contoh kedua).
Perhatikan bahwa saya hanya melakukannya ke file, tetapi mudah untuk mengubah perilaku sesuai selera Anda.
Namun ini adalah CoDec.
Dengan sedikit lebih banyak pekerjaan, Anda dapat membangun kelas Anda dengan cara lain. Saya menganggap konstruktor default untuk instance itu, lalu saya memperbarui dict kelas.
Edit
Dengan beberapa penelitian saya menemukan cara untuk menggeneralisasi tanpa perlu panggilan metode register SUPERCLASS , menggunakan metaclass
sumber
Kamu bisa memakai
dimana
Untuk solusi generik, bukti masa depan.
sumber
Gunakan
json
modul ( baru dalam Python 2.6 ) atausimplejson
modul yang hampir selalu diinstal.sumber