HTML / Javascript: cara mengakses data JSON yang dimuat dalam tag script dengan set src


90

Saya memiliki file JSON yang saya buat di server yang ingin saya jadikan dapat diakses di klien karena halamannya dapat dilihat. Pada dasarnya yang ingin saya capai adalah:

Saya memiliki tag berikut yang dideklarasikan di dokumen html saya:

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

File yang dirujuk dalam sumbernya memiliki data JSON. Seperti yang saya lihat, data telah diunduh, seperti yang terjadi dengan skrip.

Sekarang, bagaimana cara mengaksesnya dalam Javascript? Saya telah mencoba mengakses tag skrip, dengan dan tanpa jQuery, menggunakan banyak metode untuk mencoba mendapatkan data JSON saya, tetapi entah bagaimana ini tidak berhasil. Mendapatkannya innerHTMLakan berhasil seandainya data json ditulis sebaris dalam skrip. Yang bukan dan bukan itu yang ingin saya capai.

Permintaan JSON Jarak Jauh setelah pemuatan halaman juga bukan merupakan opsi, jika Anda ingin menyarankannya.


3
Alih-alih file json, jadikan itu file javascript yang menetapkan objek ke variabel. Pendekatan lainnya adalah dengan menggunakan ajax.
Asad Saeeduddin

3
Saran pertama adalah implementasi saat ini. Saya tidak ingin melakukannya karena saya menggunakan perilaku untuk menyampaikan struktur. Saya lebih suka menggunakan struktur untuk struktur (jika saya ingin JSON, saya akan mendapatkan JSON). Saran kedua tidak diinginkan (saya membutuhkan data ini untuk proses inisialisasi).
ChuckE

1
@ChuckE melalui <script>tag atau melalui AJAX Anda masih harus menunggu permintaan HTTP tambahan selesai. Browser tidak akan mengizinkan Anda membaca konten skrip jika Anda mengambilnya dengan atribut "src", jadi satu - satunya alternatif Anda adalah membuat permintaan AJAX.
Pointy

3
@Pointy melalui tag <script> hal-hal akan dievaluasi segera setelah diunduh. Jika saya menempatkan script json saya sebelum script js saya, data script json akan dievaluasi sebelum data script js, artinya saya tidak akan menunggu, data sudah ada. Tentang itu menjadi satu-satunya alternatif saya, saya ingin melihat beberapa dokumentasi resmi sebelum setuju dengan Anda (tidak mengatakan Anda salah, hanya itulah alasan saya menulis pertanyaan).
ChuckE

2
"Permintaan JSON Jarak Jauh setelah pemuatan halaman juga bukan merupakan opsi, jika Anda ingin menyarankannya." ... bagaimana permintaan JSON jauh berbeda dari permintaan yang dikirim oleh <script src=""></script>? Mereka berdua akan melakukan panggilan GET ke server Anda.
Ben Lesh

Jawaban:


114

Anda tidak dapat memuat JSON seperti itu, maaf.

Saya tahu Anda berpikir "mengapa saya tidak bisa saya gunakan di srcsini saja? Saya telah melihat hal-hal seperti ini ...":

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

... sederhananya, itu hanya tag skrip yang "disalahgunakan" sebagai pemegang data. Anda dapat melakukannya dengan semua jenis data. Misalnya, banyak mesin template memanfaatkan tag skrip untuk menampung template .

Anda memiliki daftar opsi singkat untuk memuat JSON Anda dari file jarak jauh:

  1. Gunakan $.get('your.json')atau metode AJAX lainnya.
  2. Tulis file yang menyetel variabel global ke json Anda. (sepertinya tipu).
  3. Tarik ke dalam iframe yang tidak terlihat, lalu kikis kontennya setelah dimuat (saya menyebutnya "mode 1997")
  4. Berkonsultasilah dengan pendeta voodoo.

Poin terakhir:

Permintaan JSON Jarak Jauh setelah pemuatan halaman juga bukan merupakan opsi, jika Anda ingin menyarankannya.

... itu tidak masuk akal. Perbedaan antara permintaan AJAX dan permintaan yang dikirim oleh browser saat memproses Anda <script src="">pada dasarnya tidak ada apa-apanya. Mereka berdua akan melakukan GET pada sumber daya. HTTP tidak peduli jika itu dilakukan karena tag skrip atau panggilan AJAX, dan begitu pula server Anda.


5
Jawaban yang bagus. Ketika Anda mengatakan "tag skrip sedang 'disalahgunakan'" yang Anda maksud adalah penggunaan tag skrip yang salah (mungkin tidak salah, tapi "kreatif")? N Anda. Opsi 2 adalah yang sudah kami miliki dalam produksi, saya sedang mencari solusi yang benar-benar json / no-js, dari eksperimen murni (saya baik-baik saja dengan itu tidak mungkin jika saya yakin itu). Mengenai poin terakhir, saya memerlukan informasi ini sebelum acara onload, dan saya tidak ingin membuat seluruh inisialisasi bergantung pada permintaan asinkron yang mungkin berbeda dalam waktu penyelesaian. Inilah perbedaan utama antara panggilan Ajax dan tag skrip.
ChuckE

1
Tidak, menurut saya itu tidak "salah", hanya saja ... "kreatif" mungkin adalah kata yang tepat untuk itu. Jika benar-benar menulis JSON ke dalam <script>tag itu mungkin, saya akan pergi ke rute itu, saya kira.
Ben Lesh

Ya, seluruh tantangan sedang memuatnya menggunakan atribut src tag skrip dan "mengaburkan" informasi ini di dokumen.
ChuckE

Nah, Anda tidak bisa menyembunyikan data dari pengguna di aplikasi browser sisi klien. Mereka cukup masuk ke alat pengembang browser mereka dan menetapkan titik putus di JavaScript dan memeriksa objek sesuka mereka.
Ben Lesh

1
@Jaydipsinh, maka Anda perlu menyelesaikan masalah CORS Anda, dan menggunakan Ajax. Ada alasan mengapa browser melarang perilaku semacam ini. Sebagian besar browser bahkan tidak akan membiarkan Anda meretas CORS dengan iframe lagi.
Ben Lesh

14

Solusi lain adalah dengan menggunakan bahasa skrip sisi server dan cukup memasukkan json-data inline. Berikut contoh yang menggunakan PHP:

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

Contoh di atas menggunakan tag skrip tambahan dengan tipe application/json. Solusi yang lebih sederhana adalah memasukkan JSON langsung ke JavaScript:

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

Keuntungan dari solusi dengan tag tambahan adalah kode JavaScript dan data JSON disimpan terpisah satu sama lain.


+ untuk konten teks. .html tidak berfungsi untuk saya pada tag skrip
Seth McClaine

9

Tampaknya ini tidak mungkin, atau setidaknya tidak didukung.

Dari spesifikasi HTML5 :

Saat digunakan untuk menyertakan blok data (sebagai lawan dari skrip), data harus disematkan sebaris , format data harus diberikan menggunakan atribut type, atribut src tidak boleh ditentukan , dan konten elemen skrip harus sesuai dengan persyaratan yang ditentukan untuk format yang digunakan.


1
Tampaknya menjadi kebijakan untuk menangani data yang lebih sensitif daripada JS dan CSS.

5

Meskipun saat ini tidak memungkinkan dengan scripttag, hal itu dimungkinkan dengan iframejika itu dari domain yang sama.

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

Untuk menggunakan cara di atas, cukup ganti atribut idand srcdengan yang Anda butuhkan. The id(yang akan kita asumsikan dalam situasi ini adalah sama dengan mySpecialId) akan digunakan untuk menyimpan data yang di window.jsonData["mySpecialId"].

Dengan kata lain, untuk setiap iframe yang memiliki iddan menggunakan onloadskrip akan memiliki data yang dimuat secara sinkron ke dalam window.jsonDataobjek di bawah yang idditentukan.

Saya melakukan ini untuk bersenang-senang dan untuk menunjukkan bahwa itu "mungkin 'tetapi saya tidak menganjurkan agar ini digunakan.


Berikut adalah alternatif yang menggunakan callback.

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

Diuji di chrome dan seharusnya berfungsi di firefox. Tidak yakin tentang IE atau Safari.


3

Saya setuju dengan Ben. Anda tidak dapat memuat / mengimpor file JSON sederhana.

Tetapi jika Anda benar-benar ingin melakukannya dan memiliki fleksibilitas untuk memperbarui file json, Anda bisa

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

tempatkan sesuatu seperti ini di file skrip Anda json-content.js

var mainjson = { your json data}

kemudian menyebutnya dari tag script

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

maka Anda dapat menggunakannya di skrip berikutnya

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

0

Alternatif lain untuk menggunakan json yang tepat dalam javascript. Karena ini adalah Javascript Object Notation Anda bisa membuat objek Anda langsung dengan notasi json. Jika Anda menyimpannya dalam file .js, Anda dapat menggunakan objek tersebut dalam aplikasi Anda. Ini adalah opsi yang berguna bagi saya ketika saya memiliki beberapa data json statis yang ingin saya cache dalam sebuah file secara terpisah dari aplikasi saya yang lain.

    //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
            }
        ]
    };
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.