加载本地JSON文件


322

我正在尝试加载本地JSON文件,但无法正常工作。这是我的JavaScript代码(使用jQuery:

var json = $.getJSON("test.json");
var data = eval("(" +json.responseText + ")");
document.write(data["a"]);

test.json文件:

{"a" : "b", "c" : "d"}

什么都没有显示,Firebug告诉我数据未定义。在Firebug中,我可以看到json.responseText它是好的且有效的,但是当我复制该行时,这很奇怪:

 var data = eval("(" +json.responseText + ")");

在Firebug的控制台中,它可以正常工作,并且我可以访问数据。

有人有解决办法吗?


当您返回JSON字符串时,您已经在检索javascript对象,无需使用eval()
yoda

1
您如何称呼“本地” json文件?在浏览器或服务器上本地?
seppo0010 2011年

2
您尚未提供足够的详细信息。该文件test.json未指定任何路径,因此,它是相对于访问它的页面位置的相对URI。因此,就像@ seppo0010所说,如果页面位于某处的远程服务器上,它将在服务器本地,而如果页面位于该file://协议访问的本地文件系统中,则它将相对于您的计算机。
hippietrail 2012年

Answers:


292

$.getJSON 是异步的,所以您应该这样做:

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

47
您是否真的被允许访问本地文件?
maasha 2012年

3
不可以,它不能是文件,但必须由Web服务器提供。
克里斯·埃里克森

15
完全正确。Chrome的安全性比Firefox或其他产品严格得多。在Chrome中,使用xhr,Josn,Xml等加载的内容几乎全部被锁定,只有一两种情况例外。
2014年

1
我尝试过,但是没有运气。控制台也没有错误:(
Govind Kailas 2014年

11
我建议使用myjson.com上传您的本地文件并从chrome浏览器访问它。
Chemical Programmer'1

167

我有相同的需求(测试我的angularjs应用),而我发现的唯一方法是使用require.js:

var json = require('./data.json'); //(with path)

注意:文件被加载一次,以后的调用将使用缓存。

有关使用nodejs读取文件的更多信息:http ://docs.nodejitsu.com/articles/file-system/how-to-read-files-in-nodejs

require.js:http: //requirejs.org/


4
如果您是在开玩笑,请记住这样做jest.dontMock('./data.json');,否则结果为空。也许在那里:)的人是有用的
哈佛Geithus

1
该代码的上下文是什么?你怎么办json
Drazen Bjelovuk

4
请提供完整的示例:我遇到错误:has not been loaded yet for context: _. Use require([])
shaijut

2
require不适用于浏览器,因为它是node.js模块。如果OP要在浏览器中加载它,则应使用fetch是正确的解决方案。
sniffingdoggo

1
是的,require是用于节点的,但是requireJS也可以在浏览器中使用:“ RequireJS是JavaScript文件和模块加载器。它已针对浏览器进行了优化,但可以在其他JavaScript环境中使用,例如Rhino和Node。 ”
Per Quested Aronsson

95

现在,您可以使用更现代的方式使用Fetch API

fetch("test.json")
  .then(response => response.json())
  .then(json => console.log(json));

所有现代浏览器均支持Fetch API。(Internet Explorer没有,但Edge有!)

资源:


1
使用Fetch API时,除非禁用安全性设置,否则是否仍然禁止访问本地文件?
LarsH

3
@LarsH显然是的,我今天早上尝试了它,并且api无法读取使用file:// scheme的本地json文件。这种方法看起来很干净,但您不能将其用于本地文件
keysl

1
@keysl好的,我想出于安全原因,可能必须采用这种方式。(您是对的,我的意思是“禁止通过该file://方案访问文件。)但这是一种非常干净的方法。感谢这个回答,我已经开始使用它了
。– LarsH

您无法使用访

89

如果要让用户选择本地json文件(文件系统上的任何位置),则可以使用以下解决方案。

它使用FileReader和JSON.parser(并且没有jquery)。

<html>
<body>

<form id="jsonFile" name="jsonFile" enctype="multipart/form-data" method="post">

  <fieldset>
    <h2>Json File</h2>
     <input type='file' id='fileinput'>
     <input type='button' id='btnLoad' value='Load' onclick='loadFile();'>
  </fieldset>
</form>


<script type="text/javascript">

  function loadFile() {
    var input, file, fr;

    if (typeof window.FileReader !== 'function') {
      alert("The file API isn't supported on this browser yet.");
      return;
    }

    input = document.getElementById('fileinput');
    if (!input) {
      alert("Um, couldn't find the fileinput element.");
    }
    else if (!input.files) {
      alert("This browser doesn't seem to support the `files` property of file inputs.");
    }
    else if (!input.files[0]) {
      alert("Please select a file before clicking 'Load'");
    }
    else {
      file = input.files[0];
      fr = new FileReader();
      fr.onload = receivedText;
      fr.readAsText(file);
    }

    function receivedText(e) {
      let lines = e.target.result;
      var newArr = JSON.parse(lines); 
    }
  }
</script>

</body>
</html>

这是FileReader的一个很好的介绍:http ://www.html5rocks.com/en/tutorials/file/dndfiles/


4
IE 8或9不支持FileReader API,但其他所有浏览器都可以:caniuse.com/#search=filereader
northben

它在Chrome中完美运行,您将在以下位置看到数据newArr
Belter

这个答案很好,并且有所不同,因为它不使用jQuery。
DigitalDesignDj

78

如果您想要快速又脏的东西,只需将数据加载到HTML文档的头部即可。

data.js

var DATA = {"a" : "b", "c" : "d"};

index.html

<html>
<head>
   <script src="data.js" ></script>
   <script src="main.js" ></script>
</head>
...
</html>

main.js

(function(){
   console.log(DATA); // {"a" : "b", "c" : "d"}
})();

我应该提一下,您的堆大小(在Chrome中)约为4GB,因此,如果您的数据大于该大小,则应该找到另一种方法。如果要检查其他浏览器,请尝试以下操作:

window.performance.memory.jsHeapSizeLimit / 1024 / 1024 / 1024 + " GBs"
// "4.046875 GBs"

您认为AMD可以工作是正确的,但我认为AMD在这里不是正确的解决方案。最简单的方法是使用$ .getJSON。谢谢
Patrick Browne 2015年

7
@PatrickBrowne是的,getJSON是一个很好的解决方案,但我认为在许多情况下,您将遇到跨域问题(例如,从S3加载数据)。
jwerre

我发现这对我来说是最简单的解决方案。JSON文件看起来几乎相同,因此没有多余的混乱(在文件的最顶部只有一个“ var xyz =“)。没有人想要他们的代码中的大数据文件。
cslotty

这在许多级别上都是错误的,我不知道它如何获得如此多的票,如果有人想看一下codepen.io/KryptoniteDove/post/…,它在这里解释了更多信息。简单的功能,例如下面的功能。实际上,这实际上不是加载JSON文档而是创建Javascript对象。这项技术不适用于真正的JSON文件。”
lesolorzanov

1
老实说,如果您只有一些预先设置的数据并且您想提供静态页面,这是一个很好的解决方案
Evan Pu

19

ES5版本

function loadJSON(callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'my_data.json', true);
    // Replace 'my_data' with the path to your file
    xobj.onreadystatechange = function() {
        if (xobj.readyState === 4 && xobj.status === 200) {
            // Required use of an anonymous callback 
            // as .open() will NOT return a value but simply returns undefined in asynchronous mode
            callback(xobj.responseText);
        }
    };
    xobj.send(null);
}

function init() {
    loadJSON(function(response) {
        // Parse JSON string into object
        var actual_JSON = JSON.parse(response);
    });
}

ES6版本

const loadJSON = (callback) => {
    let xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'my_data.json', true);
    // Replace 'my_data' with the path to your file
    xobj.onreadystatechange = () => {
        if (xobj.readyState === 4 && xobj.status === 200) {
            // Required use of an anonymous callback 
            // as .open() will NOT return a value but simply returns undefined in asynchronous mode
            callback(xobj.responseText);
        }
    };
    xobj.send(null);
}

const init = () => {
    loadJSON((response) => {
        // Parse JSON string into object
        let actual_JSON = JSON.parse(response);
    });
}


@Pier,如果您使用本地应用程序服务器,例如Tomcat或Xampp或Jboss。脚本工作
Mirko Cianfarani

@MirkoCianfarani确实是因为您未使用file:///协议,并且该文件不再被视为本地文件。
码头

@xgqfrms提取API很棒!
xgqfrms

2
//xobj.status是整数xobj.status ===“ 200”应该是xobj.status === 200
yausername

@yausername您是正确的,对于该错误状态类型,我们感到抱歉,并且它已得到纠正。
xgqfrms

14

在不了解和/或使用原始海报的实际代码解决问题的情况下,我无法相信已经回答了该问题多少次。就是说,我本人还是一个初学者(仅两个月的编码时间)。我的代码确实运行完美,但是可以随时提出任何建议。 解决方法如下:

//include the   'async':false   parameter or the object data won't get captured when loading
var json = $.getJSON({'url': "http://spoonertuner.com/projects/test/test.json", 'async': false});  

//The next line of code will filter out all the unwanted data from the object.
json = JSON.parse(json.responseText); 

//You can now access the json variable's object data like this json.a and json.c
document.write(json.a);
console.log(json);

这是编写与我上面提供的代码相同的较短方法:

var json = JSON.parse($.getJSON({'url': "http://spoonertuner.com/projects/test/test.json", 'async': false}).responseText);

您也可以使用$ .ajax代替$ .getJSON来以完全相同的方式编写代码:

var json = JSON.parse($.ajax({'url': "http://spoonertuner.com/projects/test/test.json", 'async': false}).responseText); 

最后,执行此操作的最后一种方法是将$ .ajax包装在函数中。我对此功不可没,但是我做了一些修改。我对其进行了测试,它的工作原理和产生的效果与上述代码相同。我在这里找到了这个解决方案->将json加载到变量中

var json = function () {
    var jsonTemp = null;
    $.ajax({
        'async': false,
        'url': "http://spoonertuner.com/projects/test/test.json",
        'success': function (data) {
            jsonTemp = data;
        }
    });
    return jsonTemp;
}(); 

document.write(json.a);
console.log(json);

您在上面的代码中看到的test.json文件托管在服务器上,并且包含他(原始发布者)发布的json数据对象。

{
    "a" : "b",
    "c" : "d"
}

11

我很惊讶没有提到从es6导入(与小文件一起使用)

例如: import test from './test.json'

webpack 2 < json-loader.json文件使用默认值。

https://webpack.js.org/guides/migrating/#json-loader-is-not-required-moremore

对于TypeScript

import test from 'json-loader!./test.json';

TS2307(TS)找不到模块'json-loader!./ suburbs.json'

为了使其正常工作,我必须先声明该模块。我希望这可以为某人节省几个小时。

declare module "json-loader!*" {
  let json: any;
  export default json;
}

...

import test from 'json-loader!./test.json';

如果我试图忽略loaderjson-loader我得到了以下错误的webpack

突破性变化:使用装载程序时,不再允许省略“ -loader”后缀。您需要指定'json-loader'而不是'json',请参阅https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed


1
简单直接。
Our_Benefactors 19-10-22

当网页加载文件:协议时,不能使用es6 import语句。
Onno van der Zee

6

可以这样尝试(但也请注意,JavaScript无法访问客户端文件系统):

$.getJSON('test.json', function(data) {
  console.log(data);
});


4

尝试(未成功)加载本地json文件时找到此线程。这个解决方案对我有用...

function load_json(src) {
  var head = document.getElementsByTagName('head')[0];

  //use class, as we can't reference by id
  var element = head.getElementsByClassName("json")[0];

  try {
    element.parentNode.removeChild(element);
  } catch (e) {
    //
  }

  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = src;
  script.className = "json";
  script.async = false;
  head.appendChild(script);

  //call the postload function after a slight delay to allow the json to load
  window.setTimeout(postloadfunction, 100)
}

...这样使用...

load_json("test2.html.js")

...这就是<head>...

<head>
  <script type="text/javascript" src="test.html.js" class="json"></script>
</head>

2
这似乎不是很可重用。例如,如果json文件由远程服务器提供,则100ms超时可能不足以加载。由于时间取决于客户端的连接速度,因此对于连接缓慢的客户端,您将必须设置一个非常长的超时时间。简而言之,不应使用setTimeout等待资源加载。
Kenny806

1
Kenny806-这是为了解决一个特定的问题-加载本地资源(用于非托管网页),所以这确实意味着它不是非常可重用的。Web托管页面的资源加载解决方案有1000多种。这不是解决方案,这是一个解决方案。更改超时非常简单。通过删除超时,您是否建议无限等待是可接受的?
TechSpud 2015年

2
我不是在建议无限等待,而是在建议使用一种技术,该技术可让您在文件加载完成后立即做出反应。我的超时问题是,您总是必须等待它完成。即使文件将在10毫秒内加载,您仍将等待100毫秒。是的,调整超时很容易,但是建议您每次加载另一个文件时或文件大小更改时(为了优化等待时间)都更改代码。恕我直言,这种解决方案是错误的,将来可能会引起很多麻烦,特别是当其他人尝试使用它时。
Kenny806

使用此脚本的任何人都应将其用作自己的脚本的基础。您有权就此脚本是否错误发表自己的意见。为什么不建议替代解决方案?这绝对不适用于所有用例。它为我工作,从本地html页面加载本地文件。我对这个问题分享了我的解决方案,希望它能对其他人有所帮助。您是否要加载本地资源?为什么不根据要加载的文件将超时值作为变量传递?本地文件上的Ajax非常有限。
TechSpud 2015年

1
使用onreadystatechange或onload并为它们提供功能可能会更好。script.onload =函数名;
Shane Best

4

在TypeScript中,您可以使用import加载本地JSON文件。例如加载font.json:

import * as fontJson from '../../public/fonts/font_name.json';

这需要一个tsconfig标志--resolveJsonModule:

// tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
}

有关更多信息,请参见打字稿的发行说明:https : //www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html


可能会写出更多详细信息,因为答案有点难以理解。

3

在angular(或任何其他框架)中,可以使用http加载,我可以使用类似以下的方式:

this.http.get(<path_to_your_json_file))
 .success((data) => console.log(data));

希望这可以帮助。


3

我所做的只是编辑JSON文件。

myfile.json => myfile.js

在JSON文件中,(使其成为JS变量)

{name: "Whatever"} => var x = {name: "Whatever"}

在最后,

export default x;

然后,

import JsonObj from './myfile.js';


3

如果您将本地数组用于JSON-如问题(test.json)中的示例所示,则可以parseJSON()使用JQuery 的方法->

var obj = jQuery.parseJSON('{"name":"John"}');
alert( obj.name === "John" );

getJSON() 用于从远程站点获取JSON-无法在本地使用(除非您使用的是本地HTTP Server)


2
$.ajax({
       url: "Scripts/testingJSON.json",
           //force to handle it as text
       dataType: "text",
            success: function (dataTest) {

                //data downloaded so we call parseJSON function 
                //and pass downloaded data
                var json = $.parseJSON(dataTest);
                //now json variable contains data in json format
                //let's display a few items
                $.each(json, function (i, jsonObjectList) {
                for (var index = 0; index < jsonObjectList.listValue_.length;index++) {
                      alert(jsonObjectList.listKey_[index][0] + " -- " + jsonObjectList.listValue_[index].description_);
                      }
                 });


             }
  });

1

我喜欢使用的一种方法是用对象文字填充/包装json,然后使用.jsonp文件扩展名保存文件。此方法还会使原始json文件(test.json)保持不变,因为您将使用新的jsonp文件(test.jsonp)。包装器上的名称可以是任何名称,但确实必须与用于处理jsonp的回调函数的名称相同。我将以您发布的test.json为例,显示“ test.jsonp”文件的jsonp包装器。

json_callback({"a" : "b", "c" : "d"});

接下来,在脚本中创建一个具有全局范围的可重用变量,以保存返回的JSON。这将使返回的JSON数据可用于脚本中的所有其他函数,而不仅是回调函数。

var myJSON;

接下来是一个简单的函数,可以通过脚本注入来检索json。请注意,由于IE不支持jQuery .append方法,因此我们不能在此处使用jQuery将脚本附加到文档头。在下面的代码中注释掉的jQuery方法将在支持.append方法的其他浏览器上运行。它被包括作为参考以显示差异。

function getLocalJSON(json_url){
    var json_script  = document.createElement('script');
    json_script.type = 'text/javascript';
    json_script.src  = json_url;
    json_script.id   = 'json_script';
    document.getElementsByTagName('head')[0].appendChild(json_script);
    // $('head')[0].append(json_script); DOES NOT WORK in IE (.append method not supported)
}

接下来是一个简短的回调函数(与jsonp包装器同名),用于将json结果数据放入全局变量中。

function json_callback(response){
    myJSON = response;            // Clone response JSON to myJSON object
    $('#json_script').remove();   // Remove json_script from the document
}

现在,脚本的任何功能都可以使用点表示法来访问json数据。举个例子:

console.log(myJSON.a); // Outputs 'b' to console
console.log(myJSON.c); // Outputs 'd' to console

该方法可能与您惯常使用的方法有所不同,但是具有许多优点。首先,可以在本地或使用相同功能的服务器中加载相同的jsonp文件。值得一提的是,jsonp已经采用了跨域友好的格式,并且可以轻松地与REST类型的API一起使用。

当然,没有错误处理功能,但是为什么需要一个?如果您无法使用此方法获取json数据,那么您可以打赌您在json本身内部存在一些问题,我会在一个不错的JSON验证程序上进行检查。


1

您可以将json放在javascript文件中。可以使用jQuery在本地(甚至在Chrome中)加载getScript()功能。

map-01.js文件:

var json = '{"layers":6, "worldWidth":500, "worldHeight":400}'

main.js

$.getScript('map-01.js')
    .done(function (script, textStatus) {
        var map = JSON.parse(json); //json is declared in the js file
        console.log("world width: " + map.worldWidth);
        drawMap(map);
    })
    .fail(function (jqxhr, settings, exception) {
        console.log("error loading map: " + exception);
    });

输出:

world width: 500

请注意,在js文件中声明并分配了json变量。


0

我没有使用Google的Closure库找到任何解决方案。因此,为了完成供将来访问者使用的列表,以下是使用Closure库从本地文件加载JSON的方法:

goog.net.XhrIo.send('../appData.json', function(evt) {
  var xhr = evt.target;
  var obj = xhr.getResponseJson(); //JSON parsed as Javascript object
  console.log(obj);
});

0

json_str = String.raw`[{"name": "Jeeva"}, {"name": "Kumar"}]`;
obj = JSON.parse(json_str);

console.log(obj[0]["name"]);

我是为我的cordova应用程序执行此操作的,就像我为JSON创建了一个新的javascript文件并将JSON数据粘贴到String.raw然后解析为JSON.parse


如果是javascript文件,为什么要这样做而不是简单地使用JavaScript Object Notation(JSON): obj = [{"name": "Jeeva"}, {"name": "Kumar"}]
NunoAndré17年

我之所以使用它,是因为我使用ajax提取了一些JSON数据(以字符串形式提供),所以我习惯将其JSON.parse转换为JavaScript对象
Jeeva,2017年

0
function readTextFile(srcfile) {
        try { //this is for IE
            var fso = new ActiveXObject("Scripting.FileSystemObject");;
            if (fso.FileExists(srcfile)) {
                var fileReader = fso.OpenTextFile(srcfile, 1);
                var line = fileReader.ReadLine();
                var jsonOutput = JSON.parse(line); 
            }

        } catch (e) {

        }
}

readTextFile("C:\\Users\\someuser\\json.txt");

首先,我要做的是从“网络”选项卡中记录服务的网络流量,然后从响应主体中将json对象复制并保存在本地文件中。然后使用本地文件名调用该函数,您应该能够在上面的jsonOutout中看到json对象。


2
请说明您的解决方案,而不只是粘贴代码。只有解释其如何解决问题的解决方案才对社区有所帮助。
gmuraleekrishna

注意:需要InternetExplorer
Sancarn '18

0

对我有用的是:

输入:

http://ip_address//some_folder_name//render_output.html?relative/path/to/json/fie.json

JavaScript代码:

<html>
<head>

<style>
pre {}
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
</style>

<script>
function output(inp) {
    document.body.appendChild(document.createElement('pre')).innerHTML = inp;
}

function gethtmlcontents(){
    path = window.location.search.substr(1)
    var rawFile = new XMLHttpRequest();
    var my_file = rawFile.open("GET", path, true)  // Synchronous File Read
    //alert('Starting to read text')
    rawFile.onreadystatechange = function ()
    {
        //alert("I am here");
        if(rawFile.readyState === 4)
        {
            if(rawFile.status === 200 || rawFile.status == 0)
            {
                var allText = rawFile.responseText;
                //alert(allText)
                var json_format = JSON.stringify(JSON.parse(allText), null, 8)
                //output(json_format)
                output(syntaxHighlight(json_format));
            }
        }
    }
    rawFile.send(null);
}

function syntaxHighlight(json) {
    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'number';
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'key';
            } else {
                cls = 'string';
            }
        } else if (/true|false/.test(match)) {
            cls = 'boolean';
        } else if (/null/.test(match)) {
            cls = 'null';
        }
        return '<span class="' + cls + '">' + match + '</span>';
    });
}

gethtmlcontents();
</script>
</head>
<body>
</body>
</html>

-4

如果您在本地计算机上安装了Python(或者您不介意安装一个),这是我使用的与本地JSON文件访问问题无关的浏览器解决方法:

通过创建将数据作为JavaScript对象返回的函数,将JSON文件转换为JavaScript。然后,您可以使用<script>标记加载它并调用该函数以获取所需的数据。

Python代码

import json


def json2js(jsonfilepath, functionname='getData'):
    """function converting json file to javascript file: json_data -> json_data.js
    :param jsonfilepath: path to json file
    :param functionname: name of javascript function which will return the data
    :return None
    """
    # load json data
    with open(jsonfilepath,'r') as jsonfile:
        data = json.load(jsonfile)
    # write transformed javascript file
    with open(jsonfilepath+'.js', 'w') as jsfile:
        jsfile.write('function '+functionname+'(){return ')
        jsfile.write(json.dumps(data))
        jsfile.write(';}')

if __name__ == '__main__':
    from sys import argv
    l = len(argv)
    if l == 2:
        json2js(argv[1])
    elif l == 3:
        json2js(argv[1], argv[2])
    else:
        raise ValueError('Usage: python pathTo/json2js.py jsonfilepath [jsfunctionname]')
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.