将本地JSON文件加载到变量中。

164

我正在尝试将一个.json文件加载到JavaScript变量中,但是我无法使其工作。可能只是一个小错误,但我找不到它。

当我使用静态数据时,一切都很正常,像这样:

var json = {
  id: "whatever",
  name: "start",
  children: [{
      "id": "0.9685",
      "name": " contents:queue"
    }, {
      "id": "0.79281",
      "name": " contents:mqq_error"
    }
  }]
}

我将括号中的所有内容放入一个content.json文件中,并尝试按照这里所述,将其加载到本地JavaScript变量中:load json into variable

var json = (function() {
  var json = null;
  $.ajax({
    'async': false,
    'global': false,
    'url': "/content.json",
    'dataType': "json",
    'success': function(data) {
      json = data;
    }
  });
  return json;
})();

我使用 Chrome 调试程序运行它,但它总是告诉我变量 json 的值为 nullcontent.json 文件与调用它的 .js 文件位于同一目录中。

我错过了什么?


1
你的文件URL是/content.json,这意味着该文件位于Web应用程序的根目录。将其更改为content.json(不带斜杠),以便将其指向与脚本文件放置在同一目录中的位置。仅当您的脚本文件位于根目录时才会起作用。 - Samich
1
文件位于WebContent\jit\content.json。我尝试了'url': "/WebContent/jit/content.json",但变量仍为空。 - PogoMips
10个回答

154

我的解决方案,就像在这里回答的一样,是使用:

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

文件只加载一次,后续请求使用缓存。
编辑:为避免缓存,这里提供了一个辅助函数,来自于评论中给出的这篇博客文章,使用fs模块:
var readJson = (path, cb) => {
  fs.readFile(require.resolve(path), (err, data) => {
    if (err)
      cb(err)
    else
      cb(null, JSON.parse(data))
  })
}

72
想要说明的是,这个解决方案需要另外一个名为RequireJS的库。 - Luis Kabongo
4
如何避免缓存? - nono
2
根据Guilherme Oenning的建议,不建议使用require读取JSON文件。https://goenning.net/2016/04/14/stop-reading-json-files-with-require/ - Sangimed
3
简而言之,缓存在单元测试中给他带来了麻烦,因此他提供了一个辅助函数以避免缓存(@nono请注意)。 - Ehvince
@Ehvince 哦,我没注意到,因为我没有读整篇文章。谢谢你 :-) - Sangimed

86

对于ES6/ES2015,你可以直接像这样导入

// example.json
{
    "name": "testing"
}


// ES6/ES2015
// app.js
import * as data from './example.json';
const {name} = data;
console.log(name); // output 'testing'

如果您使用 Typescript,您可以这样声明 json 模块:

// tying.d.ts
declare module "*.json" {
    const value: any;
    export default value;
}
自 Typescript 2.9+ 起,你可以在 tsconfig.json 的编译器选项中添加 --resolveJsonModule
{
  "compilerOptions": {
    "target": "es5",
     ...
    "resolveJsonModule": true,
     ...
  },
  ...
}

7
Chrome v72 中 import 关键字无法使用 - 仍会出现 Uncaught SyntaxError: Unexpected token * 错误。 - 1000Gbps
5
当我使用这个时,data似乎是一个模块,但data.default是该对象。 - Dustin Michels
1
我试图在控制台中运行此代码,但是没有成功。这段代码无法在node v12.4.0和babel-node 6.26.0上运行。我总是收到“SyntaxError: Unexpected token *”的错误提示。 - mario199
4
对于ES6/ES2015,您可以直接进行导入。当我执行import * as data from './example.json'时,似乎出现了一个控制台错误,原因是mime类型错误。 - Fallenreaper
2
如果我使用 import * as data from './example.json';,那么 data 只是一个模块,但是 data.default 才是对象。但是当我使用 import data from './example.json'; 时,data 就是对象,更加适用。 - user10294571
显示剩余2条评论

46

如果您直接将对象粘贴到content.json中,则它是无效的JSON。除非值为数字、布尔、null或组合(数组或对象),否则JSON键值必须用双引号包装(而不是单引号')。JSON不能包含函数或undefined值。下面是您的对象作为有效JSON的示例。

{
  "id": "whatever",
  "name": "start",
  "children": [
    {
      "id": "0.9685",
      "name": " contents:queue"
    },
    {
      "id": "0.79281",
      "name": " contents:mqq_error"
    }
  ]
}

你还多了一个 }


2
我简直不敢相信这样就解决了...为什么在.js文件中直接嵌入而不使用双引号可以工作,但在.json文件中却不行?这毫无道理... - PogoMips
20
JSON和JavaScript对象是两个不同的东西,尽管它们看起来很相似。 - adeneo
2
@Kevin B "...除非该值是数字[或布尔值]。" - Jacob Beauchamp
2
只是一个小提示:您可以使用像 https://jsonlint.com/ 这样的 JSON 验证器来检查您的 JSON 数据,以确保在使用之前数据格式正确。 - Marco Panichi

12

没有使用 require 或 fs 的解决方案:

var json = []
fetch('./content.json').then(response => json = response.json())

7

来自未来的答案。
在2022年,我们为JS文件引入了import assertions api以导入JSON文件。

import myjson from "./myjson.json" assert { type: "json" };
console.log(myjson);

浏览器支持: 直到2022年9月,只有基于chromium的浏览器和safari被支持。

阅读更多,请查看:v8 import assertions帖子


6

内置的node.js模块fs会根据您的需求异步或同步地执行它。

您可以使用var fs = require('fs');来加载它。

异步

fs.readFile('./content.json', (err, data) => {
    if (err)
      console.log(err);
    else {
      var json = JSON.parse(data);
    //your code using json object
    }
})

同步

var json = JSON.parse(fs.readFileSync('./content.json').toString());

4

可能存在两个问题:

  1. AJAX is asynchronous, so json will be undefined when you return from the outer function. When the file has been loaded, the callback function will set json to some value but at that time, nobody cares anymore.

    I see that you tried to fix this with 'async': false. To check whether this works, add this line to the code and check your browser's console:

    console.log(['json', json]);
    
  2. The path might be wrong. Use the same path that you used to load your script in the HTML document. So if your script is js/script.js, use js/content.json

    Some browsers can show you which URLs they tried to access and how that went (success/error codes, HTML headers, etc). Check your browser's development tools to see what happens.


也许他的 jQuery 版本还不支持这个功能?我已经改进了措辞。 - Aaron Digulla

3

对于像~/my-app/src/db/abc.json文件中给定的json格式:

  [
      {
        "name":"Ankit",
        "id":1
      },
      {
        "name":"Aditi",
        "id":2
      },
      {
        "name":"Avani",
        "id":3
      }
  ]

要将文件导入到 .js 文件中,例如 ~/my-app/src/app.js:

 const json = require("./db/abc.json");

 class Arena extends React.Component{
   render(){
     return(
       json.map((user)=>
        {
          return(
            <div>{user.name}</div>
          )
        }
       )
      }
    );
   }
 }

 export default Arena;

输出:

Ankit Aditi Avani

4
这是对一个与此处所问问题无关的问题的回答。 - Kevin B
这很棒,但是这个问题是关于用户尝试将一个对象字面量复制到一个 .json 文件中,然后使用 ajax 加载它,只是他们的对象字面量不符合 JSON 的格式。虽然安装 React 并使用 require 导入可能在某些情况下确实有效,但并没有真正帮助到 这个 情况。 - Kevin B
作为一条注释:在所有其他答案中发布链接到此答案的评论可能被视为过度自我推销,并且尝试编辑答案是破坏行为。您的评论已被删除,请不要再次进行此类编辑。 - Brad Larson

1

获取免费的JSON文件,请前往https://jsonplaceholder.typicode.com/

如果需要导入JSON文件,请尝试以下方法

const dataframe1=require('./users.json');
console.log(dataframe1);

1
从包含问题中共享的json的output.json文件中导出特定值到一个变量,比如说VAR:
export VAR=$(jq -r '.children.id' output.json)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接