Apakah valid untuk mendefinisikan fungsi dalam hasil JSON?

98

Bagian dari tanggapan JSON situs web memiliki ini (... ditambahkan untuk konteks):

{..., now:function(){return(new Date).getTime()}, ...}

Apakah menambahkan fungsi anonim ke JSON valid? Saya berharap setiap kali Anda mengakses 'waktu' untuk mengembalikan nilai yang berbeda.

Zachary Scott
sumber
Apakah JSON berhasil mengurai oleh browser? Jika demikian maka ya itu sah (dalam hal itu).
harschware
7
@harschware - itu benar hanya karena JSON terkait dengan javascript. Sebagai format serialisasi data independen bahasa, itu salah dan merupakan jalan bermasalah untuk berjalan.
jsoverson
@jsoverson - Saya setuju. Lihat jawaban saya di bawah.
harschware
1
Mudah untuk menjawab pertanyaan ini pada diri Anda: terbuka web up kit inspektur dan menjalankan: JSON.parse('{now:function(){return(new Date).getTime()}'). Inspektur berkata: Uncaught SyntaxError: Unexpected token nSekilas spesifikasi JSON mengkonfirmasi hal ini. Fokus pada bagian 'nilai'.
Mark E. Haase

Jawaban:

103

Tidak.

JSON murni dimaksudkan sebagai bahasa deskripsi data. Seperti dicatat di http://www.json.org , ini adalah "format pertukaran data ringan." - bukan bahasa pemrograman.

Sesuai http://en.wikipedia.org/wiki/JSON , "tipe dasar" yang didukung adalah:

  • Angka (integer, real, atau floating point)
  • String (Unicode kutip ganda dengan pelolosan garis miring terbalik)
  • Boolean (benar dan salah)
  • Array (urutan nilai yang diurutkan, dipisahkan dengan koma dan diapit oleh tanda kurung siku)
  • Objek (kumpulan kunci: pasangan nilai, dipisahkan dengan koma, dan diapit tanda kurung kurawal)
  • null
Mike
sumber
2
@Tokopedia Zim, tidak dan untuk membandingkan sesuatu dengan null apa yang saya lakukan adalah ini a==null?1:a.toString()==""Apa yang dikatakannya jika a = null maka ia mengembalikan 1 / true, jika "" berarti string kosong Anda juga mendapatkan 1 / true .. jika itu bukan null atau "" maka itu akan mengembalikan 0 / false, Anda bisa mereplikasi ini lagi untuk bekerja dengan [] dan {} cukup menambahkan ?1:a==[]?1:a.toString()=={}.toString();ke cuplikan prev saya. jadi mungkin fungsi ini akan membantu Anda. isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})Saya akan menggunakan ?1:0alih-alih ?true:falsetetapi (benar / salah)
JamesM-SiteGen
10
Pada saat yang sama, fungsi juga merupakan data.
argyle
2
Saya mendarat di sini sambil mencari cara untuk mengambil "data lebih lanjut" menggunakan JSON. Akan sangat baik untuk memberi tahu klien (dari server) bagaimana mendapatkan data lebih lanjut, tanpa klien khawatir tentang api REST atau lebih yang akan dipanggil berikutnya.
Ravindranath Akila
3
@RavindranathAkila REST menyiratkan bahwa kemungkinan panggilan API berikutnya diekspos dalam panggilan tersebut. Dengan kata lain: permintaan REST yang Anda lakukan, memberi tahu Anda permintaan di masa mendatang, yang mungkin ingin Anda lakukan (berdasarkan logika keputusan aplikasi dan datanya). Contoh sempurna untuk ini adalah API Github, tempat elemen data dikembalikan - tetapi beberapa di antaranya mengarah ke sumber daya permintaan API lainnya.
Jens A. Koch
1
@ Jens-AndréKoch Terima kasih! Akan memeriksanya
Ravindranath Akila
16

Masalahnya adalah JSON sebagai bahasa definisi data berevolusi dari JSON sebagai JavaScript Object Notation. Karena Javascript mendukung eval pada JSON, maka sah untuk meletakkan kode JSON di dalam JSON (dalam kasus penggunaan itu). Jika Anda menggunakan JSON untuk meneruskan data dari jarak jauh, maka menurut saya itu adalah praktik yang buruk untuk meletakkan metode di JSON karena Anda mungkin tidak memodelkan interaksi klien-server Anda dengan baik. Dan, selanjutnya, ketika ingin menggunakan JSON sebagai bahasa deskripsi data, saya akan mengatakan Anda bisa mendapatkan masalah dengan menyematkan metode karena beberapa parser JSON ditulis hanya dengan deskripsi data dan mungkin tidak mendukung definisi metode dalam struktur.

Entri Wikipedia JSON menjadi alasan yang baik untuk tidak menyertakan metode di JSON, dengan alasan masalah keamanan:

Kecuali Anda benar-benar mempercayai sumber teks, dan Anda memiliki kebutuhan untuk mengurai dan menerima teks yang tidak sepenuhnya sesuai dengan JSON, Anda harus menghindari eval () dan menggunakan JSON.parse () atau pengurai khusus JSON lainnya. Pengurai JSON hanya akan mengenali teks JSON dan akan menolak teks lain, yang mungkin berisi JavaScript yang jahat. Di browser yang menyediakan dukungan JSON asli, pengurai JSON juga jauh lebih cepat daripada eval. Diharapkan bahwa dukungan JSON asli akan disertakan dalam standar ECMAScript berikutnya.

perangkat keras
sumber
2
Anda mungkin menggunakan istilah JSON dalam bahasa sehari-hari, tetapi secara resmi "JSON" adalah standar ECMA yang tidak menampilkan objek fungsi yang akan dikodekan. Seharusnya tidak ada ambiguitas yang kemampuan yang Anda maksud ketika Anda mengatakan "JSON" - itulah inti memiliki standar.
Mark E. Haase
Setuju itu benar hari ini. Saya tidak memiliki sumber untuk dikutip, tetapi saya yakin JSON adalah istilah yang diciptakan sebelum ECMA masuk ke dalam permainan Javascript, dan sebelum JSON adalah format pertukaran data standar ... maka saya menggunakan istilah 'berevolusi'
harschware
@harschware Menurut RFC 4627, JSON dibuat dari ECMA.
Jenna Sloan
9

Mari kita kutip salah satu spesifikasinya - http://tools.ietf.org/html/rfc7159#section-12

The The JavaScript Object Notation (JSON) Data Interchange Format Keterangan negara:

JSON adalah bagian dari JavaScript, tetapi tidak termasuk penugasan dan pemanggilan.

Karena sintaks JSON dipinjam dari JavaScript, fungsi "eval ()" bahasa itu dapat digunakan untuk mengurai teks JSON. Ini biasanya merupakan risiko keamanan yang tidak dapat diterima, karena teks
dapat berisi kode yang dapat dieksekusi bersama dengan deklarasi data
. Pertimbangan yang sama berlaku untuk penggunaan fungsi serupa eval () dalam bahasa pemrograman lain di mana teks JSON sesuai dengan
sintaks bahasa itu.

Jadi semua jawaban yang menyatakan bahwa fungsi itu bukan bagian dari standar JSON adalah benar.

Jawaban resminya adalah: Tidak, tidak valid untuk mendefinisikan fungsi dalam hasil JSON!


Jawabannya bisa ya, karena "kode adalah data" dan "data adalah kode". Meskipun JSON digunakan sebagai format serialisasi data independen bahasa, tunneling "kode" melalui jenis lain akan berfungsi.

String JSON mungkin digunakan untuk meneruskan fungsi JS ke browser sisi klien untuk dieksekusi.

[{"data":[["1","2"],["3","4"]],"aFunction":"function(){return \"foo bar\";}"}]

Ini mengarah ke pertanyaan seperti: Bagaimana " Jalankan kode JavaScript yang disimpan sebagai string ".

Bersiaplah, untuk menaikkan bendera "eval () is evil" dan tempelkan tanda "jangan gunakan terowongan melalui JSON" di sebelahnya.

Jens A. Koch
sumber
7

Sejauh yang saya tahu, itu tidak standar. Sekilas di http://json.org/ mengkonfirmasi ini.

jldupont.dll
sumber
4

Tidak, jelas tidak.

Jika Anda menggunakan serializer JSON yang layak, itu tidak akan membiarkan Anda membuat serialisasi fungsi seperti itu. Ini OBJEK yang valid, tetapi bukan JSON yang valid. Apa pun maksud situs web itu, itu tidak mengirimkan JSON yang valid.

jvenema
sumber
2
Saya menggunakan JSON-Lib dan menganggapnya sebagai serializer yang hebat. Dari [halaman penggunaan] (json-lib.sourceforge.net/usage.html) Anda dapat melihatnya akan membuat serialisasi fungsi dengan baik
harschware
Menarik ... Saya belum pernah melihat itu sebelumnya. Ini jelas bukan untuk menentukan ( json.org secara eksplisit menyatakan bahwa JSON adalah bahasa independen, yang definisi fungsinya tidak), tetapi tetap menarik.
jvenema
Lucu bahwa itu seharusnya bahasa independen tetapi JSON singkatan dari JavaScript Object Notation hmm aneh ..
Nate-Wilkins
3

JSON secara eksplisit mengecualikan fungsi karena tidak dimaksudkan sebagai struktur data khusus JavaScript (terlepas dari nama JS).

Tatu Ulmanen
sumber
3

Jawaban singkatnya adalah TIDAK ...

JSON adalah format teks yang sepenuhnya tidak bergantung pada bahasa tetapi menggunakan konvensi yang akrab bagi pemrogram bahasa keluarga C, termasuk C, C ++, C #, Java, JavaScript, Perl, Python, dan banyak lainnya. Properti ini menjadikan JSON bahasa pertukaran data yang ideal.

Perhatikan alasan mengapa:

Saat bertukar data antara browser dan server, data hanya dapat berupa teks.

JSON adalah teks, dan kita dapat mengonversi objek JavaScript apa pun menjadi JSON, dan mengirim JSON ke server.

Kami juga dapat mengonversi JSON apa pun yang diterima dari server menjadi objek JavaScript.

Dengan cara ini kita dapat bekerja dengan data sebagai objek JavaScript, tanpa penguraian dan terjemahan yang rumit.

Tapi tunggu ...

Masih ada cara untuk menyimpan fungsi Anda, secara luas tidak disarankan untuk itu, tetapi masih memungkinkan:

Kami berkata, Anda dapat menyimpan string... bagaimana jika mengubah fungsi Anda menjadi string?

const data = {func: '()=>"a FUNC"'};

Kemudian Anda dapat merangkai data menggunakan JSON.stringify(data)dan kemudian menggunakan JSON.parseuntuk menguraikannya (jika langkah ini diperlukan) ...

Dan eval untuk menjalankan fungsi string (sebelum melakukan itu, beri tahu Anda menggunakan eval secara luas tidak disarankan):

eval(data.func)(); //return "a FUNC"
Alireza
sumber
0

Melalui menggunakan NodeJS (sintaks commonJS) saya bisa mendapatkan jenis fungsi ini berfungsi, saya awalnya hanya memiliki struktur JSON di dalam beberapa file JS eksternal, tetapi saya ingin struktur itu lebih dari sebuah Kelas, dengan metode yang dapat diputuskan di menjalankan waktu.

Deklarasi 'Pelaksana' di myJSON tidak diperlukan.

var myJSON = {
    "Hello": "World",
    "Executor": ""
}

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}
Mitchell Spangler
sumber
-3

Ekspresi fungsi di JSON sepenuhnya dimungkinkan, namun jangan lupa untuk membungkusnya dengan tanda kutip ganda. Berikut adalah contoh yang diambil dari desain database noSQL:

{
  "_id": "_design/testdb",
  "views": {
    "byName": {
      "map": "function(doc){if(doc.name){emit(doc.name,doc.code)}}"
    }
  }
}

Eimantas Pėlikis
sumber
Pertanyaannya adalah tentang fungsi, bukan string. JSON mendukung nilai string, tetapi tidak mendukung fungsi. Lihat jawaban Mike untuk detailnya
jannis
@jannis mungkin saja. jika Anda menambahkan fungsi memohon sendiri seperti. orang-orang di sini rupanya tidak tahu jawabannya.
Roj
-4

meskipun eval tidak disarankan, ini berfungsi:

<!DOCTYPE html>
<html>
<body>

<h2>Convert a string written in JSON format, into a JavaScript function.</h2>

<p id="demo"></p>

<script>
    function test(val){return val + " it's OK;}
    var someVar = "yup";
    var myObj = { "func": "test(someVar);" };
    document.getElementById("demo").innerHTML = eval(myObj.func);
</script>

</body>
</html>
pascati
sumber
1
menolak karena tidak perlu menggunakan HTML dalam contoh, ini adalah gaya pengkodean 5 tahun, ada kutipan yang hilang, dan, file JSON tidak seharusnya berisi fungsi, jika mereka tidak dapat diserialkan, atau disimpan di a no sql DB,
Martijn Scheffer
-5

Tinggalkan kutipannya ...

var a = {"b":function(){alert('hello world');} };

a.b();
Clif Collins
sumber
Ini JavaScript, pertanyaannya tentang JSON.
Quentin