Saya telah menemukan bahwa ketika berikut ini dijalankan, modul json python (termasuk sejak 2.6) mengubah kunci kamus int menjadi string.
>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'
Apakah ada cara mudah untuk mempertahankan kunci sebagai int, tanpa perlu mengurai string pada dump dan load. Saya percaya itu akan mungkin menggunakan kait yang disediakan oleh modul json, tetapi sekali lagi ini masih membutuhkan parsing. Apakah mungkin ada argumen yang saya abaikan? tepuk tangan, chaz
Sub-pertanyaan: Terima kasih atas jawabannya. Melihat json berfungsi seperti yang saya takuti, apakah ada cara mudah untuk menyampaikan jenis kunci dengan mungkin mengurai output dari dump? Juga saya harus mencatat kode yang melakukan dumping dan kode yang mengunduh objek json dari server dan memuatnya, keduanya ditulis oleh saya.
Jawaban:
Ini adalah salah satu perbedaan halus di antara berbagai koleksi pemetaan yang dapat menggigit Anda. JSON memperlakukan kunci sebagai string; Python mendukung kunci yang berbeda hanya dengan tipe yang berbeda.
Dalam Python (dan tampaknya dalam Lua), kunci pemetaan (kamus atau tabel, masing-masing) adalah referensi objek. Dalam Python, mereka harus menjadi tipe yang tidak dapat diubah, atau mereka harus menjadi objek yang mengimplementasikan sebuah
__hash__
metode. (Dokumen Lua menyarankan agar ia secara otomatis menggunakan ID objek sebagai hash / kunci bahkan untuk objek yang bisa berubah dan bergantung pada string internal untuk memastikan bahwa string yang setara dipetakan ke objek yang sama).Di Perl, Javascript, awk dan banyak bahasa lainnya, kunci untuk hash, array asosiatif atau apapun sebutannya untuk bahasa yang diberikan, adalah string (atau "skalar" di Perl). Dalam perl
$foo{1}, $foo{1.0}, and $foo{"1"}
semua referensi ke pemetaan yang sama di%foo
--- kunci dievaluasi sebagai skalar!JSON dimulai sebagai teknologi serialisasi Javascript. (JSON singkatan dari J ava S cript O bject N otation .) Secara alami JSON mengimplementasikan semantik untuk notasi pemetaannya yang konsisten dengan semantik pemetaannya.
Jika kedua ujung serialisasi Anda adalah Python maka Anda akan lebih baik menggunakan acar. Jika Anda benar-benar perlu mengubahnya kembali dari JSON menjadi objek Python asli, saya kira Anda memiliki beberapa pilihan. Pertama, Anda dapat mencoba (
try: ... except: ...
) untuk mengonversi kunci apa pun menjadi angka jika pencarian kamus gagal. Alternatifnya, jika Anda menambahkan kode ke ujung yang lain (pembuat serial atau generator data JSON ini) maka Anda dapat membuatnya melakukan serialisasi JSON pada setiap nilai kunci --- menyediakannya sebagai daftar kunci. (Kemudian kode Python Anda pertama-tama akan mengulang daftar kunci, membuat instance / deserialisasi ke dalam objek Python asli ... dan kemudian menggunakannya untuk mengakses nilai dari pemetaan).sumber
Tidak, tidak ada yang namanya kunci Angka dalam JavaScript. Semua properti objek diubah menjadi String.
Ini dapat menyebabkan beberapa perilaku yang tampak aneh:
Objek JavaScript bukanlah pemetaan yang tepat seperti yang Anda pahami dalam bahasa seperti Python, dan menggunakan kunci yang bukan String menghasilkan keanehan. Inilah sebabnya mengapa JSON selalu secara eksplisit menulis kunci sebagai string, meski tampaknya tidak perlu.
sumber
999999999999999999999
diubah menjadi'999999999999999999999'
?Number
jenis adalah IEEE 754 ganda nilai floating point: Anda mendapatkan 53 bit mantissa, sehingga Anda dapat menyimpan hingga 2⁵³ (9007199254740992) dengan akurasi integer; di luar itu bilangan bulat akan dibulatkan ke nilai lain (karenanya 9007199254740993 === 9007199254740992). 999999999999999999999 dibulatkan ke 1000000000000000000000, yangtoString
representasi defaultnya adalah1e+21
.Alternatifnya, Anda juga dapat mencoba mengonversi kamus ke daftar format [(k1, v1), (k2, v2)] sambil menyandikannya menggunakan json, dan mengubahnya kembali ke kamus setelah mendekodekannya kembali.
Saya percaya ini akan membutuhkan lebih banyak pekerjaan seperti memiliki semacam bendera untuk mengidentifikasi apa semua parameter yang akan dikonversi ke kamus setelah mendekodekannya kembali dari json.sumber
Menjawab subpertanyaan Anda:
Itu bisa dicapai dengan menggunakan
json.loads(jsonDict, object_hook=jsonKeys2int)
Fungsi ini juga akan bekerja untuk dicts bersarang dan menggunakan pemahaman dict.
Jika Anda ingin memasukkan nilai juga, gunakan:
Yang menguji contoh nilai dan melemparkannya hanya jika itu adalah objek string (unicode tepatnya).
Kedua fungsi tersebut mengasumsikan kunci (dan nilai) menjadi bilangan bulat.
Terimakasih untuk:
Bagaimana cara menggunakan if / else dalam pemahaman kamus?
Ubah kunci string menjadi int dalam Kamus
sumber
Saya telah digigit oleh masalah yang sama. Seperti yang ditunjukkan orang lain, di JSON, kunci pemetaan harus berupa string. Anda dapat melakukan salah satu dari dua hal. Anda dapat menggunakan pustaka JSON yang tidak terlalu ketat, seperti demjson , yang mengizinkan string integer. Jika tidak ada program lain (atau tidak ada program lain dalam bahasa lain) yang akan membacanya, Anda seharusnya baik-baik saja. Atau Anda dapat menggunakan bahasa serialisasi yang berbeda. Saya tidak menyarankan acar. Sulit untuk dibaca, dan tidak dirancang untuk aman . Sebagai gantinya, saya menyarankan YAML, yang (hampir) superset dari JSON, dan memungkinkan kunci integer. (Setidaknya PyYAML melakukannya.)
sumber
Ubah kamus menjadi string dengan menggunakan
str(dict)
lalu ubah kembali menjadi dict dengan melakukan ini:sumber
Inilah solusi saya! Saya dulu
object_hook
, ini berguna bila Anda telah bersarangjson
Ada filter hanya untuk mem-parsing kunci json ke int. Anda juga dapat menggunakan
int(v) if v.lstrip('-').isdigit() else v
filter untuk nilai json.sumber
Saya membuat perpanjangan yang sangat sederhana dari jawaban Murmel yang menurut saya akan bekerja pada kamus yang cukup sewenang-wenang (termasuk bersarang) dengan asumsi itu dapat dibuang oleh JSON di tempat pertama. Setiap kunci yang dapat diartikan sebagai bilangan bulat akan dilemparkan ke int. Tidak diragukan lagi ini tidak terlalu efisien, tetapi berfungsi untuk tujuan saya menyimpan ke dan memuat dari string json.
Asumsikan bahwa semua kunci dalam dict asli adalah bilangan bulat jika dapat diubah menjadi int, maka ini akan mengembalikan kamus asli setelah disimpan sebagai json. misalnya
sumber
Anda dapat menulis
json.dumps
sendiri, berikut adalah contoh dari djson : encoder.py . Anda bisa menggunakannya seperti ini:sumber