【问题标题】:HTML/Javascript: how to access JSON data loaded in a script tag with src setHTML/Javascript:如何访问在带有 src 集的脚本标签中加载的 JSON 数据
【发布时间】:2021-12-21 18:33:18
【问题描述】:

我有我在服务器中生成的这个 JSON 文件,我希望在客户端可以访问该页面,因为该页面是可见的。基本上我想要实现的是:

我在我的 html 文档中声明了以下标签:

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

源中引用的文件包含 JSON 数据。正如我所见,数据已被下载,就像脚本一样。

现在,我如何在 Javascript 中访问它?我尝试使用多种方法尝试获取我的 JSON 数据,但不知何故这不起作用。如果将 json 数据内联写入脚本中,那么获取它的 innerHTML 就可以了。它不是,也不是我想要达到的目标。

页面加载后的远程 JSON 请求也不是一个选项,以防您想建议。

【问题讨论】:

  • 而不是 json 文件,将其设为将对象分配给变量的 javascript 文件。另一种方法是使用 ajax。
  • 第一个建议是当前的实现。我不想这样做,因为我正在使用行为来传递结构。我更喜欢对结构使用结构(如果我想要 JSON,我会得到 JSON)。不需要第二个建议(我需要这些数据用于初始化过程)。
  • @ChuckE 通过&lt;script&gt; 标签或通过AJAX,您仍然需要等待额外的HTTP 请求完成。如果您使用“src”属性获取脚本内容,浏览器将不允许您读取脚本内容,因此您的唯一替代方法是发出 AJAX 请求。
  • @Pointy 通过
  • “页面加载后的远程 JSON 请求也不是一个选项,以防你想建议。” ... JSON 请求与&lt;script src=""&gt;&lt;/script&gt; 发送的请求有何不同?他们都将对您的服务器进行 GET 调用。

标签: javascript json html script-tag


【解决方案1】:

虽然目前无法使用 script 标记,但如果它来自同一个域,则可以使用 iframe

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

要使用上述内容,只需将idsrc 属性替换为您需要的属性。 id(我们假设在这种情况下等于mySpecialId)将用于在window.jsonData["mySpecialId"] 中存储数据

换句话说,对于每个具有id 并使用onload 脚本的iframe,都会将该数据同步 加载到指定id 下的window.jsonData 对象中。

我这样做是为了好玩,并表明它是“可能的”,但我确实建议使用它。


这是一个使用回调的替代方法。

<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 中测试,应该可以在 firefox 中使用。不确定 IE 或 Safari。

【讨论】:

    【解决方案2】:

    在你的脚本文件json-content.js中放置类似的东西

    var mainjson = { your json data}
    

    然后从脚本标签调用它

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

    然后你可以在下一个脚本中使用它

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

    【讨论】:

      【解决方案3】:

      我同意本的观点。您无法加载/导入简单的 JSON 文件。

      但如果你绝对想这样做并且可以灵活地更新 json 文件,你可以

      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>
      

      【讨论】:

        【解决方案4】:

        在 javascript 中使用精确 json 的另一种方法。由于它是 Javascript 对象表示法,您可以直接使用 json 表示法创建您的对象。如果将其存储在 .js 文件中,则可以在应用程序中使用该对象。当我有一些静态 json 数据我想与我的应用程序的其余部分分开缓存在一个文件中时,这对我来说是一个有用的选项。

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

        【讨论】:

          【解决方案5】:

          如果您需要从另一个域加载 JSON: http://en.wikipedia.org/wiki/JSONP
          但是请注意潜在的 XSSI 攻击: https://www.scip.ch/en/?labs.20160414

          如果是同一个域,那么就使用 Ajax。

          【讨论】:

          • JSONP 不适用于 JSON 格式的结果。此外,作为参数传递给脚本的 JSONP 参数是由服务器定义的……您可能无权访问。
          【解决方案6】:

          检查这个答案:https://stackoverflow.com/a/7346598/1764509

          $.getJSON("test.json", function(json) {
              console.log(json); // this will show the info it in firebug console
          });
          

          【讨论】:

          • $.getJSON() 是一个 ajax 调用。
          • 如何在链接的 HTML 文件而不是控制台中显示信息?
          【解决方案7】:

          这似乎是不可能的,或者至少不受支持。

          来自HTML5 specification

          当用于包含数据块(相对于脚本)时,数据必须内嵌,数据的格式必须使用type属性给出, 不得指定 src 属性,并且脚本元素的内容必须符合为使用的格式定义的要求。

          【讨论】:

          • 似乎是一种处理数据比 JS 和 CSS 更敏感的策略。
          【解决方案8】:

          另一种解决方案是使用服务器端脚本语言并简单地包含 json-data 内联。下面是一个使用 PHP 的例子:

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

          上面的例子使用了一个额外的脚本标签,类型为application/json。一个更简单的解决方案是将 JSON 直接包含到 JavaScript 中:

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

          带有额外标签的解决方案的优点是 JavaScript 代码和 JSON 数据保持相互分离。

          【讨论】:

          • + 用于文本内容。 .html 在脚本标签上对我不起作用
          • 在中间包含服务器端代码会降低代码模块化和维护的可能性。
          【解决方案9】:

          抱歉,您不能这样加载 JSON。

          我知道你在想“为什么我不能在这里使用src?我见过这样的东西......”:

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

          ...简单地说,这只是脚本标签被“滥用”为数据持有者。您可以使用各种数据来做到这一点。例如,a lot of templating engines leverage script tags to hold templates

          您有一个从远程文件加载 JSON 的选项的简短列表:

          1. 使用$.get('your.json') 或其他一些这样的AJAX 方法。
          2. 编写一个文件,为您的 json 设置一个全局变量。 (看起来很虚伪)。
          3. 将其拉入一个不可见的 iframe,然后在加载后抓取其中的内容(我称之为“1997 模式”)
          4. 咨询伏都教牧师。

          最后一点:

          页面加载后的远程 JSON 请求也不是一个选项,如果您想建议的话。

          ...这没有意义。 AJAX 请求和浏览器在处理您的&lt;script src=""&gt; 时发送的请求之间的区别基本上没有什么区别。他们都会对资源进行 GET 操作。 HTTP 不在乎它是否因为脚本标签或 AJAX 调用而完成,您的服务器也不会。

          【讨论】:

          • 很好的答案。当您说“脚本标签被'滥用'”时,您的意思是使用脚本标签是错误的(也许不是错的,而是“创造性的”)?你的 n。 2 选项是我们在生产中已经拥有的选项,我一直在寻找一个严格的 json/no-js 解决方案,纯粹是实验(如果我确定它是不可能的,我很好)。关于最后一点,我在 onload 事件之前需要这些信息,并且我不想让整个初始化依赖于可能在完成时间上有所不同的异步请求。这是 Ajax 调用和脚本标记之间的主要区别。
          • 不,我不认为这是“错误的”,只是……“创意”可能是一个很好的词。如果实际上将 JSON 写入 &lt;script&gt; 标记是可能的,我想我会走那条路。
          • 是的,整个挑战是使用脚本标签 src 属性加载它并在文档中“混淆”此信息。
          • 好吧,您无法在客户端浏览器应用程序中真正向用户隐藏数据。他们可以直接进入浏览器的开发工具,在 JavaScript 中设置断点,然后检查他们喜欢的对象。
          • @Jaydipsinh,那么您需要解决您的 CORS 问题,并使用 Ajax。浏览器不允许这种行为是有原因的。大多数浏览器甚至不再允许您使用 iframe 破解 CORS。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-13
          相关资源
          最近更新 更多