HTML / Javascript: Zugriff auf JSON-Daten, die in ein Skript-Tag mit src-Set geladen wurden

89

Ich habe diese JSON-Datei, die ich auf dem Server generiere, den ich auf dem Client zugänglich machen möchte, da die Seite sichtbar ist. Grundsätzlich möchte ich Folgendes erreichen:

Ich habe das folgende Tag in meinem HTML-Dokument deklariert:

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

Die in ihrer Quelle angegebene Datei enthält JSON-Daten. Wie ich gesehen habe, wurden Daten heruntergeladen, genau wie bei den Skripten.

Wie greife ich nun in Javascript darauf zu? Ich habe versucht, mit und ohne jQuery mit einer Vielzahl von Methoden auf das Skript-Tag zuzugreifen, um meine JSON-Daten abzurufen, aber irgendwie funktioniert dies nicht. Es innerHTMLhätte funktioniert, wenn die JSON-Daten inline in das Skript geschrieben worden wären. Was es nicht war und was ich nicht erreichen will.

Eine Remote-JSON-Anforderung nach dem Laden der Seite ist ebenfalls keine Option, falls Sie dies vorschlagen möchten.

ChuckE
quelle
3
Machen Sie es anstelle einer JSON-Datei zu einer Javascript-Datei, die das Objekt einer Variablen zuweist. Der andere Ansatz ist die Verwendung von Ajax.
Asad Saeeduddin
3
Der erste Vorschlag ist die aktuelle Implementierung. Ich möchte es nicht tun, weil ich Verhalten verwende, um Struktur zu liefern. Ich würde es vorziehen, Struktur für Struktur zu verwenden (wenn ich JSON möchte, bekomme ich JSON). Ein zweiter Vorschlag ist nicht erwünscht (ich benötige diese Daten für den Initialisierungsprozess).
ChuckE
1
@ChuckE über ein <script>Tag oder über AJAX müssen Sie noch warten, bis eine zusätzliche HTTP-Anforderung abgeschlossen ist. Der Browser lässt Sie den Skriptinhalt nicht lesen, wenn Sie ihn mit einem "src" -Attribut abrufen. Daher besteht Ihre einzige Alternative darin, eine AJAX-Anfrage zu stellen.
Pointy
3
@Pointy durch ein <script> -Tag wird ausgewertet, sobald es heruntergeladen wird. Wenn ich mein JSON-Skript vor mein JS-Skript setze, werden die JSON-Skriptdaten vor den JS-Skriptdaten ausgewertet. Das heißt, ich werde nicht warten, da die Daten bereits vorhanden sind. Da dies meine einzige Alternative ist, würde ich gerne eine offizielle Dokumentation sehen, bevor ich Ihnen zustimme (ohne zu sagen, dass Sie falsch liegen, genau das war genau der Grund, warum ich die Frage geschrieben habe).
ChuckE
2
"Eine Remote-JSON-Anforderung nach dem Laden der Seite ist ebenfalls keine Option, falls Sie dies vorschlagen möchten." ... wie unterscheidet sich eine JSON-Anfrage so sehr von einer Anfrage von a <script src=""></script>? Beide führen GET-Anrufe gegen Ihren Server durch.
Ben Lesh

Antworten:

112

Sie können JSON leider nicht so laden.

Ich weiß, dass Sie denken "Warum kann ich nicht einfach srchier verwenden? Ich habe solche Sachen gesehen ...":

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

... um es einfach auszudrücken, das war nur das Skript-Tag, das als Dateninhaber "missbraucht" wurde. Sie können dies mit allen Arten von Daten tun. Beispielsweise nutzen viele Template-Engines Skript-Tags, um Vorlagen zu speichern .

Sie haben eine kurze Liste von Optionen zum Laden Ihres JSON aus einer Remote-Datei:

  1. Verwenden Sie $.get('your.json')oder eine andere solche AJAX-Methode.
  2. Schreiben Sie eine Datei, die eine globale Variable auf Ihren JSON setzt. (scheint hokey).
  3. Ziehen Sie es in einen unsichtbaren Iframe und kratzen Sie den Inhalt nach dem Laden ab (ich nenne dies "1997-Modus").
  4. Konsultieren Sie einen Voodoo-Priester.

Letzter Punkt:

Eine Remote-JSON-Anforderung nach dem Laden der Seite ist ebenfalls keine Option, falls Sie dies vorschlagen möchten.

... das macht keinen Sinn. Der Unterschied zwischen einer AJAX-Anfrage und einer Anfrage, die der Browser während der Verarbeitung Ihrer Anfrage sendet, <script src="">ist im Wesentlichen nichts. Sie werden beide ein GET für die Ressource durchführen. HTTP ist es egal, ob dies aufgrund eines Skript-Tags oder eines AJAX-Aufrufs erfolgt, und Ihr Server auch nicht.

Ben Lesh
quelle
5
Gute Antwort. Wenn Sie sagen "das Skript-Tag wird" missbraucht "", meinen Sie damit, dass das Skript-Tag falsch (vielleicht nicht falsch, aber "kreativ") verwendet wird? Ihr n. 2 Option ist die, die wir bereits in der Produktion haben. Ich habe nach einer rein json / no-js-Lösung gesucht, aus reinem Experimentieren (ich bin damit einverstanden, dass es nicht möglich ist, wenn ich sicher bin, dass es so ist). In Bezug auf den letzten Punkt benötige ich diese Informationen vor dem Onload-Ereignis, und ich möchte nicht, dass die gesamte Initialisierung von einer asynchronen Anforderung abhängt, die in der Abschlusszeit variieren kann. Dies ist der Hauptunterschied zwischen Ajax-Aufruf und Skript-Tag.
ChuckE
1
Nein, ich denke nicht, dass es "falsch" ist, nur ... "kreativ" ist wahrscheinlich ein gutes Wort dafür. Wenn es tatsächlich <script>möglich ist, den JSON in das Tag zu schreiben , würde ich diesen Weg gehen, denke ich.
Ben Lesh
Ja, die ganze Herausforderung bestand darin, es mit dem Attribut script tag src zu laden und diese Informationen im Dokument zu "verschleiern".
ChuckE
In einer clientseitigen Browser-App können Sie Daten nicht wirklich vor Benutzern verbergen. Sie können einfach in die Entwicklertools ihres Browsers gehen und einen Haltepunkt im JavaScript festlegen und Objekte untersuchen, wie sie möchten.
Ben Lesh
1
@ Jaydipsinh, dann müssen Sie Ihre CORS-Probleme lösen und Ajax verwenden. Es gibt einen Grund, warum Browser diese Art von Verhalten nicht zulassen. Die meisten Browser lassen Sie nicht einmal mehr mit einem Iframe durch CORS hacken.
Ben Lesh
13

Eine andere Lösung wäre, eine serverseitige Skriptsprache zu verwenden und einfach json-data inline einzuschließen. Hier ist ein Beispiel, das PHP verwendet:

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

Im obigen Beispiel wird ein zusätzliches Skript-Tag mit Typ verwendet application/json. Eine noch einfachere Lösung besteht darin, den JSON direkt in das JavaScript aufzunehmen:

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

Der Vorteil der Lösung mit dem zusätzlichen Tag besteht darin, dass JavaScript-Code und JSON-Daten voneinander getrennt bleiben.

Lea Rosema
quelle
+ für Textinhalte. .html funktioniert nicht für mich auf dem Skript-Tag
Seth McClaine
9

Es scheint, dass dies nicht möglich ist oder zumindest nicht unterstützt wird.

Aus der HTML5-Spezifikation :

Bei Verwendung zum Einschließen von Datenblöcken (im Gegensatz zu Skripten) müssen die Daten inline eingebettet werden , das Format der Daten muss mithilfe des type-Attributs angegeben werden, das src-Attribut darf nicht angegeben werden und der Inhalt des Skriptelements muss übereinstimmen zu den für das verwendete Format definierten Anforderungen.

BTX9000
quelle
1
Scheint eine Richtlinie zu sein, um Daten als sensibler als JS und CSS zu behandeln.
5

Während es mit dem scriptTag derzeit nicht möglich ist , ist es mit einem möglich, iframewenn es aus derselben Domain stammt.

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

Um das oben genannte zu verwenden, ersetzen Sie einfach das Attribut idund srcdurch das, was Sie benötigen. Das id(von dem wir in dieser Situation annehmen, dass es gleich ist mySpecialId) wird zum Speichern der Daten verwendet in window.jsonData["mySpecialId"].

Mit anderen Worten, für jeden Iframe, der ein hat idund das onloadSkript verwendet, werden diese Daten synchron in das window.jsonDataObjekt unter dem geladenid angegebenen .

Ich habe das zum Spaß gemacht und um zu zeigen, dass es "möglich" ist, aber ich empfehle nicht , es zu verwenden.


Hier ist eine Alternative, die stattdessen einen Rückruf verwendet.

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

In Chrom getestet und sollte in Firefox funktionieren. Unsicher über IE oder Safari.

kemicofa Geist
quelle
3

Ich stimme Ben zu. Sie können die einfache JSON-Datei nicht laden / importieren.

Wenn Sie dies jedoch unbedingt möchten und flexibel die JSON-Datei aktualisieren möchten, können Sie dies tun

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>
Karan
quelle
2

Überprüfen Sie diese Antwort: https://stackoverflow.com/a/7346598/1764509

$.getJSON("test.json", function(json) {
    console.log(json); // this will show the info it in firebug console
});
L. Grillo
quelle
3
$ .getJSON () ist ein Ajax-Aufruf.
Tobi G.
Wie kann ich die Informationen in einer verknüpften HTML-Datei anstelle der Konsole anzeigen?
T.Doe
2

Wenn Sie JSON von einer anderen Domain laden müssen: http://en.wikipedia.org/wiki/JSONP
Beachten Sie jedoch mögliche XSSI-Angriffe: https://www.scip.ch/en/?labs.20160414

Wenn es sich um dieselbe Domain handelt, verwenden Sie einfach Ajax.

Vitaliy Kaplich
quelle
2
JSONP funktioniert nicht mit JSON-formatierten Ergebnissen. Außerdem werden die JSONP-Parameter, die als Argumente an ein Skript übergeben werden, vom Server definiert, auf den Sie möglicherweise keinen Zugriff haben.
E-Sushi
1

Platzieren Sie so etwas in Ihrer Skriptdatei json-content.js

var mainjson = { your json data}

Rufen Sie es dann vom Skript-Tag aus auf

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

dann können Sie es im nächsten Skript verwenden

<script>
console.log(mainjson)
</script>
Hossein Sedighian
quelle
0

Eine weitere Alternative zur Verwendung des exakten JSON in Javascript. Da es sich um eine Javascript-Objektnotation handelt, können Sie Ihr Objekt einfach direkt mit der JSON-Notation erstellen. Wenn Sie dies in einer .js-Datei speichern, können Sie das Objekt in Ihrer Anwendung verwenden. Dies war eine nützliche Option für mich, als ich einige statische JSON-Daten hatte, die ich getrennt vom Rest meiner App in einer Datei zwischenspeichern wollte.

    //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
            }
        ]
    };
DominicTurner
quelle