Tahu mengapa JSON mengabaikan NaN dan +/- Infinity? Ini menempatkan Javascript dalam situasi aneh di mana objek yang seharusnya serializable, tidak, jika mereka berisi nilai infinity NaN atau +/-.
Sepertinya ini telah dilemparkan ke batu: lihat RFC4627 dan ECMA-262 (bagian 24.5.2, JSON.stringify, CATATAN 4, halaman 683 dari ECMA-262 pdf pada edit terakhir):
Nomor-nomor yang terbatas dirangkai seolah-olah dengan menelepon
ToString(number)
. NaN dan Infinity terlepas dari tanda diwakili sebagai Stringnull
.
javascript
json
ecma262
Jason S
sumber
sumber
Jawaban:
Infinity
danNaN
bukan kata kunci atau sesuatu yang istimewa, itu hanya properti pada objek global (apa adanyaundefined
) dan karenanya dapat diubah. Karena alasan itulah JSON tidak memasukkannya ke dalam spec - pada intinya string JSON yang sebenarnya harus memiliki hasil yang sama dalam EcmaScript jika Anda melakukannyaeval(jsonString)
atauJSON.parse(jsonString)
.Jika diizinkan maka seseorang dapat menyuntikkan kode serupa
ke dalam forum (atau apa pun) dan kemudian penggunaan json di situs itu dapat dikompromikan.
sumber
NaN
danInfinity
nama properti, jadi sementara String (1/0) menghasilkan string"Infinity"
yang hanya representasi string dari nilai tak terhingga. Tidak mungkin untuk mewakiliNaN
atauInfinity
karena nilai literalnya adalah ES - Anda harus menggunakan ekspresi (mis. 1/0, 0/0 dll) atau pencarian properti (merujuk keInfinity
atauNaN
). Karena mereka memerlukan eksekusi kode, mereka tidak dapat dimasukkan dalam JSON.Pada pertanyaan awal: Saya setuju dengan pengguna "cbare" karena ini merupakan kelalaian yang tidak menguntungkan di JSON. IEEE754 mendefinisikan ini sebagai tiga nilai khusus dari angka floating point. Jadi JSON tidak dapat sepenuhnya mewakili angka floating point IEEE754. Bahkan lebih buruk lagi, karena JSON sebagaimana didefinisikan dalam ECMA262 5.1 bahkan tidak menentukan apakah angka-angkanya didasarkan pada IEEE754. Karena aliran desain yang dideskripsikan untuk fungsi stringify () di ECMA262 tidak menyebutkan tiga nilai IEEE khusus, orang dapat menduga bahwa maksudnya sebenarnya adalah untuk mendukung angka-angka floating point IEEE754.
Sebagai satu titik data lainnya, tidak terkait dengan pertanyaan: XML tipe data xs: float dan xs: dobel menyatakan bahwa mereka didasarkan pada angka-angka floating point IEEE754, dan mereka mendukung representasi dari tiga nilai khusus ini (Lihat W3C XSD 1.0 Bagian 2 , Datatypes).
sumber
Bisakah Anda mengadaptasi pola objek nol, dan di JSON Anda mewakili nilai-nilai seperti
Kemudian saat memeriksa, Anda dapat memeriksa jenisnya
Saya tahu di Java Anda bisa mengganti metode serialisasi untuk mengimplementasikan hal seperti itu. Tidak yakin dari mana asal serialisasi Anda, jadi saya tidak bisa memberikan detail tentang bagaimana menerapkannya dalam metode serialisasi.
sumber
undefined
bukan kata kunci, ini properti pada objek global"undefined" in this
mengembalikan true dalam lingkup global. Ini juga berarti Anda dapat melakukanundefined = 42
danif (myVar == undefined)
menjadi (pada dasarnya)myVar == 42
. Ini mengingatkan kembali pada hari-hari awal javascript ecmascript nee di manaundefined
tidak ada secara default, jadi orang hanya melakukannyavar undefined
dalam lingkup global. Konsekuensinyaundefined
tidak dapat dibuat kata kunci tanpa merusak situs yang ada, jadi kami ditakdirkan untuk selamanya menjadi properti normal.undefined
adalah properti global karena ditentukan seperti itu. Konsultasikan 15.1.1.3 dari ECMAScript-262 edisi ke-3.String "Infinity", "-Infinity", dan "NaN" semuanya memaksa ke nilai yang diharapkan di JS. Jadi saya berpendapat cara yang tepat untuk mewakili nilai-nilai ini di JSON adalah sebagai string.
Sayang JSON.stringify tidak melakukan ini secara default. Tapi ada caranya:
sumber
NaN
danInfinity
menambahkan sebagai nilai kata kunci sukatrue
danfalse
.Number("Infinity")
,Number("-Infinity")
danNumber("NaN")
JSON.parse("{ \"value\" : -1e99999 }")
mudah kembali{ value:-Infinity }
dalam javascript. Hanya saja tidak kompatibel dengan jenis nomor kustom yang bisa lebih besar dari ituJika Anda memiliki akses ke kode serialisasi, Anda mungkin mewakili Infinity sebagai 1.0e + 1024. Eksponen terlalu besar untuk diwakili dalam dobel dan ketika deserialized ini diwakili sebagai Infinity. Bekerja di webkit, tidak yakin tentang parser json lainnya!
sumber
Infinity
akan selaluInfinity
begitu, jadi mengapa tidak mendukungnya?/0
. Ini mudah diurai, langsung terlihat, dan bahkan dapat dievaluasi. Tidak dapat dimaafkan bahwa mereka belum menambahkannya ke standar:{"Not A Number":0/0,"Infinity":1/0,"Negative Infinity":-1/0}
<< Kenapa tidak?alert(eval("\"Not A Number\"") //works
alert(eval("1/0")) //also works, prints 'Infinity'
. Tidak ada alasan.IEEE Std 754-2008 saat ini mencakup definisi untuk dua representasi titik-mengambang 64-bit yang berbeda: tipe titik-floating-point 64-bit desimal dan tipe-titik floating-point biner 64-bit.
Setelah pembulatan string
.99999990000000006
adalah sama seperti.9999999
dalam representasi 64-bit biner IEEE tetapi TIDAK sama dengan.9999999
representasi 64-bit desimal IEEE. Dalam 64-bit IEEE desimal, floating-point.99999990000000006
rounds ke nilai.9999999000000001
yang tidak sama dengan nilai desimal.9999999
.Karena JSON hanya memperlakukan nilai numerik sebagai string numerik digit desimal, tidak ada cara untuk sistem yang mendukung representasi titik-biner IEEE dan floating-point desimal (seperti IBM Power) untuk menentukan yang mana dari dua kemungkinan nilai-nilai titik angka numerik IEEE yang mungkin. dimaksudkan.
sumber
Potensi penyelesaian untuk kasus-kasus seperti {"key": Infinity}:
Gagasan umum adalah mengganti kemunculan nilai yang tidak valid dengan string yang akan kami kenali saat mengurai dan menggantinya kembali dengan representasi JavaScript yang sesuai.
sumber
Alasannya dinyatakan pada halaman ii dalam Standard ECMA-404 JSON Data Interchange Syntax, 1st Edition
Alasannya bukan, seperti yang banyak diklaim, karena representasi
NaN
danInfinity
skrip ECMA. Kesederhanaan adalah prinsip desain inti JSON.sumber
Jika seperti saya Anda tidak memiliki kendali atas kode serialisasi, Anda dapat menangani nilai NaN dengan menggantinya dengan nol atau nilai lain sebagai sedikit peretasan sebagai berikut:
Intinya, .fail akan dipanggil ketika parser json asli mendeteksi token yang tidak valid. Kemudian ganti string digunakan untuk mengganti token yang tidak valid. Dalam kasus saya ini adalah pengecualian untuk serialiser untuk mengembalikan nilai NaN sehingga metode ini adalah pendekatan terbaik. Jika hasil biasanya berisi token yang tidak valid Anda akan lebih baik untuk tidak menggunakan $ .get tetapi untuk secara manual mengambil hasil JSON dan selalu menjalankan penggantian string.
sumber
{ "tune": "NaNaNaNaNaNaNaNa BATMAN", "score": NaN }