HTML / Javascript:如何访问设置了src的脚本标签中加载的JSON数据


90

我有一个在服务器中生成的JSON文件,由于该页面可见,因此我希望在客户端上对其进行访问。基本上我想实现的是:

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

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

源中引用的文件具有JSON数据。如我所见,数据已经下载,就像脚本一样。

现在,如何使用Javascript访问它?我尝试使用多种方法来访问带有和不带有jQuery的脚本标签,以尝试获取我的JSON数据,但是这不起作用。innerHTML如果将json数据内嵌在脚本中,则获取它的工作将是可行的。不是,不是我想要达到的目标。

页面加载后的远程JSON请求也不是一种选择,以防您建议这样做。


3
代替一个json文件,使其成为一个将对象分配给变量的javascript文件。另一种方法是使用ajax。
Asad Saeeduddin 2012年

3
第一个建议是当前的实现。我不想这样做,因为我使用行为来传递结构。我更喜欢将结构用于结构(如果我想要JSON,我将获取JSON)。不需要第二个建议(初始化过程中需要此数据)。
ChuckE 2012年

1
通过<script>标签或通过AJAX的@ChuckE,您仍然必须等待其他HTTP请求完成。如果使用“ src”属性获取脚本内容,浏览器将不允许您读取脚本内容,因此,唯一的选择是发出AJAX请求。
Pointy 2012年

3
下载后,将通过<script>标记的东西@Pointy进行评估。如果将json脚本放在js脚本之前,则json脚本数据将在js脚本数据之前得到评估,这意味着,我不会等待,数据已经存在。关于它是我唯一的选择,我想在与您达成协议之前先看一些官方文档(不是说您错了,这正是我写这个问题的原因)。
ChuckE 2012年

2
“如果要建议这样做,那么在页面加载后也不能选择远程JSON请求。” ... JSON请求与a发送的请求<script src=""></script>有何不同?他们都将对您的服务器进行GET调用。
Ben Lesh 2012年

Answers:


113

抱歉,您无法像这样加载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>

...简而言之,那就是脚本标签被“滥用”为数据持有人。您可以使用各种数据来做到这一点。例如,许多模板引擎利用脚本标签来保存模板

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

  1. 使用$.get('your.json')或其他某种AJAX方法。
  2. 编写一个将全局变量设置为json的文件。(似乎曲棍球)。
  3. 将其拉到不可见的iframe中,然后在加载后将其内容抓取(我称之为“ 1997模式”)
  4. 咨询巫毒教士。

最后一点:

页面加载后的远程JSON请求也不是一种选择,以防您建议这样做。

...那没有道理。AJAX请求和浏览器在处理您的请求时发送的请求之间的区别<script src="">本质上没有什么区别。他们都将对资源进行GET。HTTP不在乎是否由于脚本标记或AJAX调用而完成,您的服务器也不会。


5
好答案。当您说“脚本标签被'滥用'”时,您是说对脚本标签的使用是错误的(也许不是错误的,而是“创造性的”)使用?你的 2个选项是我们已经在生产中使用的选项,出于纯粹的实验,我一直在寻找一种严格的json / no-js解决方案(如果可以确定,我没有可能)。关于最后一点,我需要在onload事件之前获得此信息,并且我不想使整个初始化依赖于异步请求,异步请求的完成时间可能有所不同。这是Ajax调用和脚本标记之间的主要区别。
ChuckE 2012年

1
不,我认为这不是“错误”,只是……“创意”可能是一个好词。如果可以将JSON实际写入<script>标记中,我想走那条路。
Ben Lesh 2012年

是的,整个挑战是使用脚本标签src属性加载它,并在文档中“混淆”此信息。
ChuckE 2012年

好吧,您不能真正在客户端浏览器应用程序中向用户隐藏数据。他们可以进入浏览器的开发人员工具,并在JavaScript中设置断点,并根据需要检查对象。
Ben Lesh 2012年

1
@Jaydipsinh,那么您需要解决CORS问题,并使用Ajax。浏览器不允许这种行为是有原因的。大多数浏览器甚至都不再允许您使用iframe来绕过CORS。
Ben Lesh 2013年

14

另一种解决方案是利用服务器端脚本语言,并简单地内嵌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在脚本标签上对我不起作用
Seth McClaine

9

看来这是不可能的,或者至少不被支持。

根据HTML5规范

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


1
似乎是一种比JS和CSS更敏感地处理数据的策略。

5

虽然目前无法使用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>

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

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

我这样做很有趣,并表明它是“可能的”,但我建议您使用它。


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

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

经过镀铬测试,可在Firefox中使用。不确定IE或Safari。


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>



1

在您的脚本文件中放置这样的内容 json-content.js

var mainjson = { your json data}

然后从脚本标签调用它

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

那么你可以在下一个脚本中使用它

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

0

在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
            }
        ]
    };
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.