HTML / Javascript: src setiyle bir komut dosyası etiketine yüklenen JSON verilerine nasıl erişilir


91

Sayfa görüntülenebilir olduğundan istemcide erişilebilir hale getirmek istediğim sunucuda oluşturduğum bu JSON dosyasına sahibim. Temel olarak elde etmek istediğim şey:

Html belgemde aşağıdaki etiketi beyan ettim:

<script id="test" type="application/json" src="http://myresources/stuf.json">

Kaynağında belirtilen dosyanın JSON verileri var. Gördüğüm gibi, veriler, komut dosyalarında olduğu gibi indirildi.

Şimdi, ona Javascript'te nasıl erişebilirim? JSON verilerimi almaya çalışmak için çok sayıda yöntem kullanarak jQuery ile ve jQuery olmadan komut dosyası etiketine erişmeyi denedim, ancak bir şekilde bu işe yaramıyor. innerHTMLJson verileri kodda satır içi yazılsaydı , onu almak işe yarardı. Benim başarmaya çalıştığım şey değildi ve değil.

Bunu önermek istemeniz durumunda, sayfa yüklendikten sonra uzaktan JSON İsteği de bir seçenek değildir.


3
Bir json dosyası yerine, nesneyi bir değişkene atayan bir javascript dosyası yapın. Diğer yaklaşım ajax kullanmaktır.
Asad Saeeduddin

3
İlk öneri, mevcut uygulama. Yapmak istemiyorum çünkü yapıyı sağlamak için davranışı kullanıyorum. Yapı için yapı kullanmayı tercih ederim (JSON istiyorsam, JSON alacağım). İkinci öneri istenmiyor (başlatma işlemi için bu verilere ihtiyacım var).
Chuck

1
@ChuckE bir <script>etiket aracılığıyla veya AJAX aracılığıyla yine de ek bir HTTP isteğinin tamamlanmasını beklemeniz gerekecektir. Tarayıcı, komut dosyasını bir "src" özniteliğiyle getirirseniz, komut dosyası içeriğini okumanıza izin vermez, bu nedenle tek alternatifiniz bir AJAX isteği yapmaktır.
Pointy

3
Bir <script> etiketi aracılığıyla @Pointy, indirilir indirilmez değerlendirilecektir. Json betiğimi js betiğimin önüne yerleştirirsem, json betiği verileri js betiği verisinden önce değerlendirilecektir, yani beklemeyeceğim, veriler zaten orada. Bunun tek alternatifim olduğu konusunda, sizinle aynı fikirde olmadan önce bazı resmi belgeler görmek istiyorum (yanılıyorsunuz demiyorum, sadece soruyu yazmamın sebebi buydu).
ChuckE

2
"Bunu önermek istemeniz durumunda, sayfa yüklendikten sonra uzaktan JSON İsteği de bir seçenek değildir." ... JSON isteği, bir tarafından gönderilen bir istekten nasıl çok farklıdır <script src=""></script>? İkisi de sunucunuza karşı GET çağrıları yapacak.
Ben Lesh

Yanıtlar:


116

JSON'u bu şekilde yükleyemezsin, üzgünüm.

"Neden srcburada kullanamıyorum ? Bunun gibi şeyler gördüm ..." diye düşündüğünüzü biliyorum :

<script id="myJson" type="application/json">
 { 
   name: 'Foo' 
 }
</script>

<script type="text/javascript">
    $(function() {
        var x = JSON.parse($('#myJson').html());
        alert(x.name); //Foo
     });
</script>

... basitçe söylemek gerekirse, bu sadece bir veri sahibi olarak "kötüye kullanılan" komut dosyası etiketiydi. Bunu her türlü veriyle yapabilirsiniz. Örneğin, birçok şablon oluşturma motoru, şablonları tutmak için komut dosyası etiketlerinden yararlanır .

JSON dosyanızı uzak bir dosyadan yüklemek için kısa bir seçenek listeniz var:

  1. Kullan $.get('your.json')veya başka bir AJAX yöntemi.
  2. Json'unuza global bir değişken ayarlayan bir dosya yazın. (hokey görünüyor).
  3. Görünmez bir iframe içine çekin, ardından yüklendikten sonra içeriğini kazıyın (ben buna "1997 modu" diyorum)
  4. Bir vudu rahibine danışın.

Son nokta:

Bunu önermek istemeniz durumunda, sayfa yüklendikten sonra uzaktan JSON İsteği de bir seçenek değildir.

... bu mantıklı değil. AJAX isteği ile tarayıcınız işlenirken gönderilen istek arasındaki fark <script src="">aslında hiçbir şey değildir. İkisi de kaynak üzerinde bir GET yapacak. HTTP, bir komut dosyası etiketi veya AJAX çağrısı nedeniyle yapılmasını umursamaz ve sunucunuz da umursamaz.


5
Mükemmel cevap. "Komut dosyası etiketinin kötüye kullanılması" dediğinizde, bunun komut dosyası etiketinin yanlış (belki de yanlış değil, ancak "yaratıcı") kullanımı olduğunu mu kastediyorsunuz? Sizin n. 2 seçeneği, üretimde zaten sahip olduğumuz seçenek, saf deneyler dışında kesinlikle bir json / no-js çözümü arıyordum (eğer eminysem bunun mümkün olmaması sorun değil). Son nokta ile ilgili olarak, bu bilgiye onload olayından önce ihtiyacım var ve tüm başlatmanın tamamlanma süresinde değişiklik gösterebilen asenkron bir isteğe bağlı olmasını istemiyorum. Bu, Ajax çağrısı ve komut dosyası etiketi arasındaki temel farktır.
ChuckE

1
Hayır, "yanlış" olduğunu sanmıyorum, sadece ... "yaratıcı" muhtemelen bunun için iyi bir kelime. Aslında JSON'u <script>etikete yazmak mümkünse, o yola giderim, sanırım.
Ben Lesh

yeh, tüm zorluk, src komut dosyası etiketi özelliğini kullanarak onu yüklemek ve bu bilgiyi belgedeki "gizlemek" idi.
ChuckE

Bir istemci tarafı tarayıcı uygulamasında kullanıcılardan gerçekten veri gizleyemezsiniz. Tarayıcılarının geliştirici araçlarına girip JavaScript'te bir kesme noktası belirleyebilir ve nesneleri istedikleri gibi inceleyebilirler.
Ben Lesh

1
@Jaydipsinh, sonra CORS sorunlarınızı çözmeniz ve Ajax kullanmanız gerekir. Tarayıcıların bu tür davranışlara izin vermemesinin bir nedeni var. Çoğu tarayıcı, artık bir iframe ile CORS'ta yolunuzu kesmenize bile izin vermiyor.
Ben Lesh

14

Başka bir çözüm, sunucu tarafı kodlama dilini kullanmak ve yalnızca json-data satır içi eklemektir. İşte PHP kullanan bir örnek:

<script id="data" type="application/json"><?php include('stuff.json'); ?></script>
<script>
var jsonData = JSON.parse(document.getElementById('data').textContent)
</script>

Yukarıdaki örnek, type ile ekstra bir komut dosyası etiketi kullanır application/json. Daha da basit bir çözüm, JSON'yi doğrudan JavaScript'e eklemektir:

<script>var jsonData = <?php include('stuff.json');?>;</script>

Ekstra etiketli çözümün avantajı, JavaScript kodu ve JSON verilerinin birbirinden ayrı tutulmasıdır.


+ metin içeriği için. .html komut dosyası etiketinde benim için çalışmıyor
Seth McClaine

9

Görünüşe göre bu mümkün değil veya en azından desteklenmiyor.

Gönderen HTML5 özelliklerini :

Veri bloklarını dahil etmek için kullanıldığında (komut dosyalarının aksine), veriler satır içinde gömülmeli , verilerin formatı type özelliği kullanılarak verilmeli , src niteliği belirtilmemeli ve komut dosyası öğesinin içeriği uygun olmalıdır. kullanılan format için tanımlanan gereksinimlere.


1
Verileri JS ve CSS'den daha hassas olarak ele alan bir politika gibi görünüyor.

5

Şu anda scriptetiketiyle mümkün iframeolmasa da, aynı alandan olması durumunda mümkündür .

<iframe
id="mySpecialId"
src="/my/link/to/some.json"
onload="(()=>{if(!window.jsonData){window.jsonData={}}try{window.jsonData[this.id]=JSON.parse(this.contentWindow.document.body.textContent.trim())}catch(e){console.warn(e)}this.remove();})();"
onerror="((err)=>console.warn(err))();"
style="display: none;"
></iframe>

Yukarıdakileri kullanmak için idve srcözniteliğini ihtiyacınız olan şeyle değiştirmeniz yeterlidir. id(Biz bu durumda varsaydığımız eşittir mySpecialIddepolamak için kullanılacaktır) verileri dewindow.jsonData["mySpecialId"] .

Başka bir deyişle, betiği olan idve kullanan her iframe onloadiçin bu veriler , belirtilen altındaki nesneye eşzamanlı olarak yüklenir .window.jsonDataid

Eğlenmek için ve ' "mümkün ama emin göstermek için yaptım değil o kullanılmasını öneririz.


İşte bunun yerine geri arama kullanan bir alternatif.

<script>
    function someCallback(data){
        /** do something with data */
        console.log(data);

    }
    function jsonOnLoad(callback){
        const raw = this.contentWindow.document.body.textContent.trim();
        try {
          const data = JSON.parse(raw);
          /** do something with data */
          callback(data);
        }catch(e){
          console.warn(e.message);
        }
        this.remove();
    }
</script>
<!-- I frame with src pointing to json file on server, onload we apply "this" to have the iframe context, display none as we don't want to show the iframe -->
<iframe src="your/link/to/some.json" onload="jsonOnLoad.apply(this, someCallback)" style="display: none;"></iframe>

Chrome'da test edilmiştir ve firefox'ta çalışmalıdır. IE veya Safari konusunda emin değilim.


3

Ben'e katılıyorum. Basit JSON dosyasını yükleyemez / içe aktaramazsınız.

Ancak bunu kesinlikle yapmak istiyorsanız ve json dosyasını güncelleme esnekliğiniz varsa, şunları yapabilirsiniz:

my-json.js

   var myJSON = {
      id: "12ws",
      name: "smith"
    }

index.html

<head>
  <script src="my-json.js"></script>
</head>
<body onload="document.getElementById('json-holder').innerHTML = JSON.stringify(myJSON);">
  <div id="json-holder"></div>
</body>



1

komut dosyanıza buna benzer bir şey yerleştirin json-content.js

var mainjson = { your json data}

sonra onu komut dosyası etiketinden çağırın

<script src="json-content.js"></script>

sonra bir sonraki komut dosyasında kullanabilirsiniz

<script>
console.log(mainjson)
</script>

0

Javascript içinde tam json kullanmak için başka bir alternatif. Javascript Object Notation olduğu için, nesnenizi doğrudan json notasyonu ile oluşturabilirsiniz. Bunu bir .js dosyasında saklarsanız, uygulamanızda nesneyi kullanabilirsiniz. Bu, uygulamamın geri kalanından ayrı olarak bir dosyada önbelleğe almak istediğim bazı statik json verilerim olduğunda benim için kullanışlı bir seçenekti.

    //Just hard code json directly within JS
    //here I create an object CLC that represents the json!
    $scope.CLC = {
        "ContentLayouts": [
            {
                "ContentLayoutID": 1,
                "ContentLayoutTitle": "Right",
                "ContentLayoutImageUrl": "/Wasabi/Common/gfx/layout/right.png",
                "ContentLayoutIndex": 0,
                "IsDefault": true
            },
            {
                "ContentLayoutID": 2,
                "ContentLayoutTitle": "Bottom",
                "ContentLayoutImageUrl": "/Wasabi/Common/gfx/layout/bottom.png",
                "ContentLayoutIndex": 1,
                "IsDefault": false
            },
            {
                "ContentLayoutID": 3,
                "ContentLayoutTitle": "Top",
                "ContentLayoutImageUrl": "/Wasabi/Common/gfx/layout/top.png",
                "ContentLayoutIndex": 2,
                "IsDefault": false
            }
        ]
    };
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.