JSON sonuçlarında fonksiyonları tanımlamak geçerli midir?


98

Bir web sitesinin JSON yanıtının bir kısmı şuna sahipti (... bağlam için eklendi):

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

JSON'a anonim işlevler eklemek geçerli midir? 'Zaman'a her eriştiğinizde farklı bir değer döndürmesini beklerim.


JSON, tarayıcı tarafından başarıyla ayrıştırıldı mı? Eğer öyleyse o zaman evet geçerlidir (bu bakımdan).
harschware

7
@harschware - bu yalnızca JSON javascript ile ilgili olduğu için doğrudur. Dilden bağımsız bir veri serileştirme formatı olarak bu yanlıştır ve sorunlu bir yoldur.
jsoverson

@jsoverson - Katılıyorum. Aşağıdaki cevabıma bakın.
harschware

1
Açık yukarıya web kiti müfettişi ve koşmak: Kolay bu soruyu kendiniz cevap: JSON.parse('{now:function(){return(new Date).getTime()}'). Müfettiş diyor ki: JSON özelliklerineUncaught SyntaxError: Unexpected token n hızlı bir bakış bunu doğrular. 'Değer' bölümüne odaklanın.
Mark E. Haase

Yanıtlar:


103

Hayır.

JSON, tamamen bir veri açıklama dili olarak tasarlanmıştır. Üzerinde belirtildiği gibi http://www.json.org , bir "hafif bir veri değişim formatı" dir. - programlama dili değil.

Http://en.wikipedia.org/wiki/JSON uyarınca , desteklenen "temel türler" şunlardır:

  • Sayı (tam sayı, gerçek veya kayan nokta)
  • Dize (ters eğik çizgiden kaçan çift tırnaklı Unicode)
  • Boole (doğru ve yanlış)
  • Dizi (virgülle ayrılmış ve köşeli parantez içine alınmış sıralı bir değerler dizisi)
  • Nesne (anahtar koleksiyonu: değer çiftleri, virgülle ayrılmış ve kaşlı ayraçlar içine alınmış)
  • null

2
@Dr. Zim, hayır ve şeyleri null ile karşılaştırmak için yaptığım şey şudur Bu a==null?1:a.toString()=="", a = null ise 1 / true döndürdüğünü söyler, eğer boş dizge ise "" boş dizge de 1 / true alırsınız .. eğer öyleyse null değil veya "" o zaman 0 / false döndürür, bunu [] ile çalışmak için daha fazla çoğaltabilir ve {} sadece ?1:a==[]?1:a.toString()=={}.toString();önceki snippet'ime ekleyebilirsin . bu yüzden belki bu işlev size yardımcı olacaktır. isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})Bunun ?1:0yerine kullanırdım ?true:falseama (doğru / yanlış)
JamesM-SiteGen

10
Aynı zamanda, fonksiyonlar da veridir.
argyle

2
JSON kullanarak "daha fazla veri" almanın bir yolunu bulurken buraya geldim. Bir istemciye (sunucudan) daha fazla veriyi nasıl alacağını bildirmek, istemcinin daha sonra hangi REST veya benzeri api'yi arayacağı konusunda endişelenmesine gerek kalmadan iyi olurdu.
Ravindranath Akila

3
@RavindranathAkila REST, olası sonraki API çağrılarının çağrıda açığa çıkacağını ima eder. Başka bir deyişle: Yaptığınız REST talebi, gelecekte yapmak isteyebileceğiniz talepleri size söyler (uygulama karar mantığına ve verilere göre). Bunun mükemmel bir örneği, veri öğelerinin döndürüldüğü Github API'dir - ancak bazıları diğer API istek kaynaklarına yönlendirir.
Jens A. Koch

1
@ Jens-AndréKoch Teşekkürler! Kontrol edecek
Ravindranath Akila

16

Sorun, JSON'un bir veri tanımlama dili olarak JSON'dan JavaScript Nesne Gösterimi olarak evrimleşmesidir. Javascript, JSON üzerinde eval'u desteklediğinden, JSON kodunu JSON içerisine koymak meşrudur (bu kullanım durumunda). Verileri uzaktan iletmek için JSON kullanıyorsanız, o zaman JSON'a yöntemler koymanın kötü bir uygulama olduğunu söyleyebilirim çünkü istemci-sunucu etkileşiminizi iyi modellememiş olabilirsiniz. Ayrıca, JSON'u bir veri açıklama dili olarak kullanmak istediğinizde, yöntemleri yerleştirerek başınızı belaya sokabileceğinizi söyleyebilirim, çünkü bazı JSON ayrıştırıcıları yalnızca veri açıklamaları dikkate alınarak yazılmıştır ve yapıdaki yöntem tanımlarını desteklemeyebilir.

Wikipedia JSON girişi , güvenlik endişelerini öne sürerek JSON'a yöntemler dahil etmemek için iyi bir durumdur:

Metnin kaynağına kesinlikle güvenmiyorsanız ve kesinlikle JSON uyumlu olmayan metni ayrıştırıp kabul etmeniz gerekmiyorsa, eval () kullanmaktan kaçınmalı ve bunun yerine JSON.parse () veya JSON'a özgü başka bir ayrıştırıcı kullanmalısınız. JSON ayrıştırıcısı yalnızca JSON metnini tanır ve kötü niyetli JavaScript içerebilecek diğer metinleri reddeder. Yerel JSON desteği sağlayan tarayıcılarda, JSON ayrıştırıcıları da eval'dan çok daha hızlıdır. Yerel JSON desteğinin bir sonraki ECMAScript standardına dahil edilmesi beklenmektedir.


2
JSON terimini konuşma dilinde kullanıyor olabilirsiniz, ancak resmi olarak "JSON", kodlanacak işlev nesnelerini çıplak bırakmayan bir ECMA standardıdır. - sizin "JSON" deyince kastediyoruz yetenekleri hiçbir belirsizliğe yer verilmemelidir bütün mesele bir standart sahip.
Mark E. Haase

Bunun bugün doğru olduğu kabul edildi. Alıntı yapacak bir kaynağım yok, ancak JSON'un ECMA Javascript oyununa girmeden önce ve JSON standart bir veri değişim formatı olmadan önce icat edilmiş bir terim olduğuna inanıyorum ... bu nedenle 'gelişmiş' terimini kullandım
harschware

@harschware RFC 4627'ye göre JSON, ECMA'dan yapılmıştır.
Jenna Sloan

9

Spesifikasyonlardan birini alıntılayalım - http://tools.ietf.org/html/rfc7159#section-12

JavaScript Object Notation (JSON) Veri Değişim Biçimi Şartname durumları:

JSON, JavaScript'in bir alt kümesidir ancak atama ve çağrıyı hariç tutar.

JSON'un sözdizimi JavaScript'ten ödünç alındığından, JSON metinlerini ayrıştırmak için o dilin "eval ()" işlevini kullanmak mümkündür. Metin
, veri bildirimleriyle birlikte çalıştırılabilir kod içerebileceğinden , bu
genellikle kabul edilemez bir güvenlik riski oluşturur . Aynı husus, JSON metinlerinin o
dilin sözdizimine uygun olduğu diğer programlama dillerinde eval () benzeri işlevlerin kullanımı için de geçerlidir .

Dolayısıyla, hangi durumun, bu işlevlerin JSON standardının parçası olmadığı tüm yanıtlar doğrudur.

Resmi cevap: Hayır, JSON sonuçlarında fonksiyonları tanımlamak geçerli değil!


Cevap evet olabilir, çünkü "kod veridir" ve "veri koddur". JSON, dilden bağımsız bir veri serileştirme formatı olarak kullanılsa bile, diğer türler üzerinden "kod" tünellemesi çalışacaktır.

Çalıştırmak üzere istemci tarafı tarayıcıya bir JS işlevi iletmek için bir JSON dizesi kullanılabilir.

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

Bu, soruya benzer: " Dize olarak depolanan JavaScript kodu nasıl çalıştırılır ".

Hazırlıklı olun, "eval () kötüdür" bayrağınızı yükseltin ve "JSON aracılığıyla işlevleri tünelleme" bayrağını yanına yapıştırın.



4

Hayır, kesinlikle hayır.

İyi bir JSON serileştirici kullanırsanız, böyle bir işlevi serileştirmenize izin vermez. Bu geçerli bir NESNE, ancak geçerli JSON değil. Bu web sitesinin amacı ne olursa olsun, geçerli JSON göndermiyor.


2
JSON-Lib kullanıyorum ve bunun harika bir serileştirici olduğunu düşünüyorum. [Kullanım sayfasından] (json-lib.sourceforge.net/usage.html) işlevleri serileştireceğini görebilirsiniz
harschware

İlginç ... Bunu daha önce hiç görmemiştim. Kesinlikle belirtmek için değil ( json.org, JSON'un dilden bağımsız olduğunu, işlev tanımlarının olmadığını açıkça belirtir), ancak yine de ilginçtir.
jvenema

Dilden bağımsız olması komik ama JSON, JavaScript Object Notation anlamına geliyor hmm tuhaf ..
Nate-Wilkins

3

JSON, yalnızca JavaScript'ten oluşan bir veri yapısı olması amaçlanmadığı için işlevleri açıkça hariç tutar (addaki JS'ye rağmen).


3

Kısa bir cevap HAYIR ...

JSON, tamamen dilden bağımsız olan ancak C, C ++, C #, Java, JavaScript, Perl, Python ve diğerleri dahil olmak üzere C dil ailesinin programcılarına aşina olan kuralları kullanan bir metin formatıdır. Bu özellikler JSON'u ideal bir veri değişim dili yapar.

Nedenine bakın:

Bir tarayıcı ve bir sunucu arasında veri alışverişinde bulunurken, veriler yalnızca metin olabilir.

JSON metindir ve herhangi bir JavaScript nesnesini JSON'a dönüştürebilir ve sunucuya JSON gönderebiliriz.

Ayrıca sunucudan alınan herhangi bir JSON'u JavaScript nesnelerine dönüştürebiliriz.

Bu şekilde, karmaşık ayrıştırma ve çeviriler olmaksızın verilerle JavaScript nesneleri olarak çalışabiliriz.

Ama bekle ...

İşlevinizi saklamanın hala yolları var, yaygın olarak tavsiye edilmiyor , ancak yine de mümkündür:

Dedik ki, bir kaydedebilirsiniz string... peki ya fonksiyonunuzu bir dizgeye dönüştürmeye ne dersiniz?

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

Ardından, kullanarak JSON.stringify(data)ve sonra kullanarak verileri dizgeleştirebilirsiniz.JSON.parse onu ayrıştırmak için (eğer bu adım gerekliyse) ...

Ve eval bir dize işlevi yürütmek için (bu işlemden önce sadece yaygın önerilmez eval kullanarak bildirmek):

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

0

NodeJS (commonJS sözdizimi) kullanarak, bu tür bir işlevselliğin çalışmasını sağlayabildim, başlangıçta bazı harici JS dosyalarının içinde sadece bir JSON yapısına sahiptim, ancak bu yapının, karar verilebilecek yöntemlerle daha çok bir Sınıf olmasını istedim. Çalışma süresi.

MyJSON'da 'Yürütücü' beyanı gerekli değildir.

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

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}

-3

JSON'daki fonksiyon ifadeleri tamamen mümkündür, sadece çift tırnak içine almayı unutmayın. İşte noSQL veritabanı tasarımından alınan bir örnek:

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


Soru dizge değil işlev hakkındadır. JSON, dize değerlerini destekler, ancak işlevleri desteklemez. Ayrıntılar için Mike'ın cevabına bakın
jannis

@jannis yine de mümkün. gibi kendi kendini çağıran bir işlev eklerseniz. Görünüşe göre buradaki insanlar cevabı bilmiyorlar.
Roj

-4

eval önerilmez, ancak bu işe yarar:

<!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>

1
Örnekte HTML kullanmak gerekli olmadığından reddedildi, bu 5 yıllık kodlama stilidir, eksik bir alıntı vardır ve JSON dosyalarının işlevler içermesi beklenmez, eğer yaparlarsa serileştirilemezler veya depolanamazlar a no sql DB,
Martijn Scheffer

-5

Alıntıları bırak ...

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

a.b();

Bu JavaScript, soru JSON hakkında soruyor.
Quentin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.