HTML / Javascript: come accedere ai dati JSON caricati in un tag script con src impostato


90

Ho questo file JSON che generi nel server che voglio rendere accessibile sul client poiché la pagina è visualizzabile. Fondamentalmente quello che voglio ottenere è:

Ho il seguente tag dichiarato nel mio documento html:

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

Il file indicato nella sua origine contiene dati JSON. Come ho visto, i dati sono stati scaricati, proprio come accade con gli script.

Ora, come posso accedervi in ​​Javascript? Ho provato ad accedere al tag script, con e senza jQuery, utilizzando una moltitudine di metodi per provare a ottenere i miei dati JSON, ma in qualche modo questo non funziona. Il suo recupero innerHTMLavrebbe funzionato se i dati json fossero stati scritti in linea nello script. Che non era e non è quello che sto cercando di ottenere.

Anche la richiesta JSON remota dopo il caricamento della pagina non è un'opzione, nel caso in cui lo desideri suggerire.


3
Invece di un file json, rendilo un file javascript che assegna l'oggetto a una variabile. L'altro approccio consiste nell'usare ajax.
Asad Saeeduddin

3
Il primo suggerimento è l'attuale implementazione. Vorrei non farlo perché utilizzo il comportamento per fornire una struttura. Preferisco usare la struttura per la struttura (se voglio JSON, otterrò JSON). Il secondo suggerimento non è voluto (ho bisogno di questi dati per il processo di inizializzazione).
ChuckE

1
@ChuckE tramite un <script>tag o tramite AJAX dovrai comunque attendere il completamento di un'ulteriore richiesta HTTP. Il browser non ti permetterà di leggere il contenuto dello script se lo prendi con un attributo "src", quindi la tua unica alternativa è fare una richiesta AJAX.
Pointy

3
@Pointy tramite un tag <script> verrà valutato non appena viene scaricato. Se metto il mio script json prima del mio script js, i dati dello script json verranno valutati prima dei dati dello script js, ciò significa che non aspetterò, i dati sono già lì. Essendo la mia unica alternativa, mi piacerebbe vedere della documentazione ufficiale prima di essere d'accordo con te (non dico che ti sbagli, solo che era esattamente il motivo per cui ho scritto la domanda).
ChuckE

2
"Anche la richiesta JSON remota dopo il caricamento della pagina non è un'opzione, nel caso tu lo voglia suggerire." ... in che modo una richiesta JSON è così diversa da una richiesta inviata da un <script src=""></script>? Entrambi faranno chiamate GET sul tuo server.
Ben Lesh,

Risposte:


114

Non puoi caricare JSON in questo modo, mi dispiace.

So che stai pensando "perché non posso usarlo srcqui? Ho visto cose come questa ...":

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

... beh, per dirla semplicemente, quello era solo il tag script che veniva "abusato" come detentore dei dati. Puoi farlo con tutti i tipi di dati. Ad esempio, molti motori di creazione di modelli sfruttano i tag di script per contenere i modelli .

Hai un breve elenco di opzioni per caricare il tuo JSON da un file remoto:

  1. Utilizzare $.get('your.json')o un altro metodo AJAX simile.
  2. Scrivi un file che imposti una variabile globale sul tuo json. (sembra hokey).
  3. Inseriscilo in un iframe invisibile, quindi raschia il contenuto dopo che è stato caricato (la chiamo "modalità 1997")
  4. Consulta un prete vudù.

Punto finale:

Anche la richiesta JSON remota dopo il caricamento della pagina non è un'opzione, nel caso in cui lo desideri suggerire.

... non ha senso. La differenza tra una richiesta AJAX e una richiesta inviata dal browser durante l'elaborazione della tua <script src="">è essenzialmente nulla. Entrambi faranno un GET sulla risorsa. All'HTTP non importa se è fatto a causa di un tag script o di una chiamata AJAX, e nemmeno il tuo server.


5
Bella risposta. Quando dici "il tag script è stato 'abusato'" intendi dire che è un uso sbagliato (forse non sbagliato, ma "creativo") del tag script? Il tuo n. L'opzione 2 è quella che abbiamo già in produzione, cercavo una soluzione rigorosamente json / no-js, per pura sperimentazione (sto bene che non sia possibile se sono sicuro che lo sia). Per quanto riguarda il punto finale, ho bisogno di queste informazioni prima dell'evento onload e non voglio che l'intera inizializzazione dipenda da una richiesta asincrona che può variare nel tempo di completamento. Questa è la differenza fondamentale tra la chiamata Ajax e il tag script.
ChuckE

1
No, non penso che sia "sbagliato", per dire, solo ... "creativo" è probabilmente una buona parola per questo. Se <script>è possibile scrivere effettivamente il JSON nel tag, credo che seguirei quella strada.
Ben Lesh

yeh, l'intera sfida è stata caricarlo utilizzando l'attributo src del tag script e "offuscare" queste informazioni nel documento.
ChuckE

Bene, non puoi davvero nascondere i dati agli utenti in un'app browser lato client. Possono semplicemente accedere agli strumenti di sviluppo del browser e impostare un punto di interruzione in JavaScript ed esaminare gli oggetti come preferiscono.
Ben Lesh

1
@Jaydipsinh, allora devi risolvere i tuoi problemi CORS e usare Ajax. C'è un motivo per cui i browser non consentono questo tipo di comportamento. La maggior parte dei browser non ti consentirà più di hackerare CORS con un iframe.
Ben Lesh,

14

Un'altra soluzione potrebbe essere quella di utilizzare un linguaggio di scripting lato server e includere semplicemente json-data inline. Ecco un esempio che utilizza PHP:

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

L'esempio precedente utilizza un tag script aggiuntivo con type application/json. Una soluzione ancora più semplice è includere il JSON direttamente nel JavaScript:

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

Il vantaggio della soluzione con il tag aggiuntivo è che il codice JavaScript e i dati JSON vengono tenuti separati l'uno dall'altro.


+ per il contenuto di testo. .html non funziona per me sul tag script
Seth McClaine

9

Sembrerebbe che questo non sia possibile, o almeno non supportato.

Dalla specifica HTML5 :

Quando viene utilizzato per includere blocchi di dati (al contrario degli script), i dati devono essere incorporati in linea , il formato dei dati deve essere fornito utilizzando l'attributo type, l'attributo src non deve essere specificato e il contenuto dell'elemento script deve essere conforme ai requisiti definiti per il formato utilizzato.


1
Sembra essere una politica per gestire i dati come più sensibili di JS e CSS.

5

Sebbene al momento non sia possibile con il scripttag, è possibile con un iframese proviene dallo stesso dominio.

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

Per utilizzare quanto sopra, è sufficiente sostituire l' attributo ide srccon quello che ti serve. Il id(che assumeremo in questa situazione è uguale a mySpecialId) verrà utilizzato per memorizzare i dati in window.jsonData["mySpecialId"].

In altre parole, per ogni iframe che ha un ide utilizza lo onloadscript, i dati verranno caricati in modo sincronowindow.jsonData nell'oggetto sotto il file idspecificato.

L'ho fatto per divertimento e per dimostrare che è "possibile" ma non consiglio che venga utilizzato.


Ecco un'alternativa che utilizza invece una richiamata.

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

Testato in Chrome e dovrebbe funzionare in Firefox. Non sono sicuro di IE o Safari.


3

Sono d'accordo con Ben. Non è possibile caricare / importare il semplice file JSON.

Ma se vuoi assolutamente farlo e hai la flessibilità di aggiornare il file json, puoi farlo

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

inserisci qualcosa di simile nel tuo file di script json-content.js

var mainjson = { your json data}

quindi chiamalo dal tag script

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

quindi puoi usarlo nel prossimo script

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

0

Un'altra alternativa per utilizzare l'esatto json all'interno di javascript. Poiché è Javascript Object Notation, puoi semplicemente creare il tuo oggetto direttamente con la notazione json. Se lo memorizzi in un file .js puoi utilizzare l'oggetto nella tua applicazione. Questa è stata un'opzione utile per me quando avevo alcuni dati json statici che volevo memorizzare nella cache in un file separatamente dal resto della mia app.

    //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
            }
        ]
    };
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.