【问题标题】:How to import a JSON file in ECMAScript 6?如何在 ECMAScript 6 中导入 JSON 文件?
【发布时间】:2016-04-28 21:35:13
【问题描述】:

如何在 ECMAScript 6 中访问 JSON 文件?

以下不起作用:

import config from '../config.json'

如果我尝试导入 JavaScript 文件,这会很好。

【问题讨论】:

  • 这与 ES6 无关,但与您使用的模块加载器有关。语法本身很好。
  • 最简洁的方法是使用webpackjson-loader
  • ES6 支持 JSON 导入,语法如下: import * as data from './example.json';
  • @williamli 这在当今(2020 年)的浏览器中不起作用,除非有更多的事情发生(例如,像 Babel 这样重写代码的构建步骤):例如在 Chrome 中获得 “加载模块脚本失败:服务器以非 JavaScript MIME 类型“application/json”响应。根据 HTML 规范对模块脚本强制执行严格的 MIME 类型检查。”(参见规范讨论 herethis proposal repo 上的讨论。)到目前为止,需要使用以下答案之一。

标签: json import ecmascript-6


【解决方案1】:

更优雅的解决方案是使用 CommonJS 的 require 函数

createRequire 构造一个 CommonJS 的 require 函数,以便您可以使用典型的 CommonJS 功能,例如读取 JSON

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const data = require("./data.json");

【讨论】:

    【解决方案2】:

    正如 Azad 所说,正确的答案是使用 fs.readFileSync() 加载文件(或任何异步变体,例如带有回调的 fs.readFile 或带有 promises/await 的 fs.promises.readFile,然后解析JSON 与 JSON.parse()

    const packageJsonRaw = fs.readFileSync('location/to/package.json' ) 
    const packageJson = JSON.parse(packageJsonRaw )
    

    Webpack/Babel 选项不实用,除非您已经在使用该设置。

    【讨论】:

      【解决方案3】:

      使用 ES 模块导入 JSON 作为功能于 2020 年中期提交给 TC39,并且(在本次编辑时)处于第 3 阶段,这是规范接受之前的最后一个阶段(请参阅 https://github.com/tc39/proposal-json-modules更多细节)。登陆后,您可以将其用作:

      import someName from "./some/path/to/your/file.json";
      

      someName 实际上是 JSON 数据描述的 JS 对象的变量名称。 (当然,请注意,这会从 JSON 源导入 JavaScript,而不是“导入 JSON”)。

      如果您使用的是足够现代的捆绑程序(如esbuild 或类似的),或者您使用的是最新的转译器(如babel),那么您已经可以使用此语法而无需担心支持。

      或者,如果您拥有 JSON 文件的所有权,您还可以使用最少的额外代码将您的 JSON 转换为有效的 JS 文件:

      config.js

      export default
      {
        // my json here...
      }
      

      那么……

      import config from '../config.js'
      

      不允许导入现有的 .json 文件,但可以完成工作。

      【讨论】:

      • 这实际上并没有回答问题。例如,您不能简单地将 package.json 转换为 package.js。有时您想真正导入 JSON 而不是 JS。
      • 根本不是解决方案,您正在导出一个恰好与 JSON 具有相同语法的 javascript 对象。
      • 更新了问题文本;尽量避免进一步的语义辩论。
      • “将其转换为 JS”不是如何导入 JSON 文件的解决方案。那不再是 JSON 文件了。这是关于如何导入 JSON 的排名第一的谷歌结果,主要答案是不导入 JSON。
      • .js 文件里有配置更方便,因为你可以在里面有cmets。 JSON 文件不支持这个。
      【解决方案4】:

      感谢所有提出和实施JSON modulesImport Assertions 的人。从 Chrome 91 开始,可以直接导入 JSON,例如:

      // test.json
      {
          "hello": "world"
      }
      
      // Static Import
      import json from "./test.json" assert { type: "json" };
      console.log(json.hello);
      
      // Dynamic Import
      const { default: json } = await import("./test.json", { assert: { type: "json" } });
      console.log(json.hello);
      
      // Dynamic Import
      import("./test.json", { assert: { type: "json" } })
        .then(module => console.log(module.default.hello));
      
      

      注意:其他浏览器目前可能尚未实现此功能。

      【讨论】:

        【解决方案5】:

        从“./resource.json”导入数据 在 Chrome 91 中是可能的。 现在支持 JSON 模块。这允许开发人员静态导入 JSON,而不是依赖动态检索它的 fetch() 函数。

        https://www.stefanjudis.com/snippets/how-to-import-json-files-in-es-modules/

        【讨论】:

          【解决方案6】:

          如果你使用节点,你可以:

          const fs = require('fs');
          
          const { config } = JSON.parse(fs.readFileSync('../config.json'));
          

          const evaluation = require('../config.json');
          // evaluation will then contain all props, so evaluation.config
          // or you could use:
          const { config } = require('../config.json');
          

          其他:

          // config.js
          {
          // json object here
          }
          
          // script.js
          
          import { config } from '../config.js';
          

          import * from '../config.json'
          

          【讨论】:

          • const config = JSON.parse(fs.readFileSync('../config.json')); 为我工作。节点一团糟。
          • 我认为这里const { config } = JSON.parse(fs.readFileSync('../config.json')); 错过了参数'utf8',所以它应该是这样的:JSON.parse(fs.readFileSync('../package.json', 'utf8'));
          【解决方案7】:

          我正在使用

          • vuejs,版本:2.6.12
          • vuex,版本:3.6.0
          • vuex-i18n,版本:1.13.1。

          我的解决办法是:

          messages.js:

          import Vue from 'vue'
          import Vuex from 'vuex';
          import vuexI18n from 'vuex-i18n';
          import translationsPl from './messages_pl'
          import translationsEn from './messages_en'
          
          Vue.use(Vuex);
          
          export const messages = new Vuex.Store();
          
          Vue.use(vuexI18n.plugin, messages);
          
          Vue.i18n.add('en', translationsEn);
          Vue.i18n.add('pl', translationsPl);
          
          Vue.i18n.set('pl');
          

          messages_pl.json:

          {
              "loadingSpinner.text:"Ładowanie..."
          }
          

          messages_en.json:

          {
              "loadingSpinner.default.text":"Loading..."
          }
          

          majn.js

          import {messages} from './i18n/messages'
          Vue.use(messages);
          

          【讨论】:

            【解决方案8】:

            导入 JSON 文件仍处于试验阶段。它可以通过下面的标志来支持。

            --experimental-json-modules

            否则,您可以直接使用fs 加载相对于import.meta.url 的JSON 文件:-

            import { readFile } from 'fs/promises';
            const config = JSON.parse(await readFile(new URL('../config.json', import.meta.url)));
            

            你也可以使用module.createRequire()

            import { createRequire } from 'module';
            const require = createRequire(import.meta.url);
            const config = require('../config.json');
            

            【讨论】:

              【解决方案9】:

              我使用它安装插件“babel-plugin-inline-json-import”,然后在 .balberc 中添加插件。

              1. 安装插件

                npm install --save-dev babel-plugin-inline-json-import

              2. babelrc 中的配置插件

                “插件”:[ “内联 json 导入” ]

              这是我使用它的代码

              import es from './es.json'
              import en from './en.json'
              
              export const dictionary = { es, en }
              

              【讨论】:

                【解决方案10】:

                除了其他答案之外,在 Node.js 中,甚至可以在 ES 模块中使用 require 来读取 JSON 文件。我发现这在读取其他包中的文件时特别有用,因为它利用 Node 自己的 module resolution strategy 来定位文件。

                ES 模块中的require 必须首先使用createRequire 创建。

                这是一个完整的例子:

                import { createRequire } from 'module';
                
                const require = createRequire(import.meta.url);
                const packageJson = require('typescript/package.json');
                console.log(`You have TypeScript version ${packageJson.version} installed.`);
                

                在安装了 TypeScript 的项目中,上面的代码将从 package.json 读取并打印 TypeScript 版本号。

                【讨论】:

                  【解决方案11】:

                  对于 NodeJS v12 及更高版本,--experimental-json-modules 可以解决问题,无需 babel 的任何帮助。

                  https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_experimental_json_modules

                  但是是以commonjs形式导入的,所以import { a, b } from 'c.json'还不支持。

                  但你可以这样做:

                  import c from 'c.json';
                  const { a, b } = c;
                  

                  【讨论】:

                    【解决方案12】:

                    只需这样做:

                    import * as importedConfig from '../config.json';
                    

                    然后像下面这样使用它:

                    const config = importedConfig.default;
                    

                    【讨论】:

                    • 这在浏览器中本身并不适用,尽管它可能与您似乎正在使用的任何构建系统(Babel 或其他)结合使用。
                    【解决方案13】:

                    在带有 fetch 的浏览器中(现在基本上全部):

                    目前,我们不能import 具有 JSON mime 类型的文件,只能使用 JavaScript mime 类型的文件。这可能是将来添加的功能 (official discussion)。

                    fetch('./file.json')
                      .then(response => response.json())
                      .then(obj => console.log(obj))
                    

                    在 Node.js v13.2+ 中:

                    目前需要--experimental-json-modules flag,否则默认不支持。

                    尝试运行

                    node --input-type module --experimental-json-modules --eval "import obj from './file.json'; console.log(obj)"
                    

                    并查看输出到控制台的 obj 内容。

                    【讨论】:

                    • 我在浏览器中做了第一个,它成功了
                    【解决方案14】:

                    在 TypeScript 或使用 Babel 中,您可以在代码中导入 json 文件。

                    // Babel
                    
                    import * as data from './example.json';
                    const word = data.name;
                    console.log(word); // output 'testing'
                    

                    参考: https://hackernoon.com/import-json-into-typescript-8d465beded79

                    【讨论】:

                    • 只是添加到这个(typescript json import)你现在可以简单地将它添加到你的 tsconfig... { "compilerOptions": { "resolveJsonModule": true } }
                    • 有浏览器支持吗?我在当前的 FF 上试过这个并得到错误 Loading failed for the module with source "example.json";在 Chrome 上,我得到“加载模块脚本失败:服务器以“application/json”的非 JavaScript MIME 类型响应。对每个 HTML 规范的模块脚本强制执行严格的 MIME 类型检查。”
                    • 我突然想到,当你说“在 ES6 中”时,你实际上是指“在 TS 中”——我以为你在谈论 tsc 的代码 emitted但事实并非如此。我正在尝试在浏览器 (<script type="module">) 上本地运行 ES6 模块,如果直接运行 import 行,就会出现上述错误。如果我错了,请纠正我,实际上你的意思是在实际的 ES6 中可以从 JSON 导入。
                    • 当我说“任何浏览器都支持这个”时,我的意思不是“在你通过 Babel 转换它之后”。您链接的第一篇文章有​​ TS 将 import 语句转换为节点 require()(试试看!),第二个链接没有说明 JSON 导入。这里的问题不在于解析器或模块系统,而是 loader —— 浏览器的加载器不会解析除 Javascript 之外的任何内容的导入。在幕后,您总是必须使用 AJAX 调用(fetch / XHR)并解析结果,即使您的构建工具链将其抽象出来。
                    • 这样我们就不会在兴奋时忘记,转译器所做的只是将 json 内容内联到输出文件的常量中,因为在 javascript 的世界中,这确实是唯一安全的方式(除了 ajaxing 这是一个不同的故事)
                    【解决方案15】:

                    根据您的构建工具和 JSON 文件中的数据结构,可能需要导入 default

                    import { default as config } from '../config.json';
                    

                    例如在Next.js中使用

                    【讨论】:

                    • 为 TypeScript 添加了注释,以确保 resolveJsonModule 在您 tsconfig.json 中是 true
                    【解决方案16】:

                    很遗憾,ES6/ES2015 不支持通过模块导入语法加载 JSON。 但是...

                    有很多方法可以做到这一点。根据您的需要,您可以研究如何在 JavaScript 中读取文件(如果您在浏览器中运行,window.FileReader 可能是一个选项)或使用other questions 中描述的其他一些加载器(假设您使用的是 NodeJS) .

                    IMO 最简单的方法可能是将 JSON 作为 JS 对象放入 ES6 模块并导出。这样你就可以在需要的地方导入它。

                    如果您使用 Webpack,导入 JSON 文件 will work by default(自 webpack >= v2.0.0)也值得注意。

                    import config from '../config.json';
                    

                    【讨论】:

                    • 没有必要把它放在一个字符串中。毕竟它叫 JSON,而不是 JSSN。
                    • 另外,torazaburo 在之前删除的答案中解释说:没有 ES6“模块系统”;有一个由特定加载器实现的 API。任何加载器都可以做它想做的任何事情,包括支持 JSON 文件的导入。例如,加载器可能会选择支持 import foo from './directory 作为 import directory/index.js 的意思
                    • 事实上 ES6/ES2015 确实支持通过导入语法加载 JSON:import * as data from './example.json';
                    • +1 用于提醒 webpack 自动执行此操作。不过要小心,如果你有“test: /.js/”,webpack 会尝试将你的 json 文件编译为 JavaScript。 #失败。要修复它,请将其更改为“test: /.js$/”
                    • webpack 是基于 nodejs 的,不是吗?
                    【解决方案17】:

                    有点晚了,但我在尝试为我的网络应用提供分析时偶然发现了同样的问题,该分析涉及基于 package.json 版本发送应用版本。

                    配置如下:React + Redux,Webpack 3.5.6

                    json-loader 自从 Webpack 2+ 以来并没有做太多事情,所以在摆弄了一些之后,我最终将它删除了。

                    实际上对我有用的解决方案就是使用 fetch。 虽然这很可能会强制执行一些代码更改以适应异步方法,但它运行良好,特别是考虑到 fetch 将提供动态 json 解码这一事实。

                    原来是这样:

                      fetch('../../package.json')
                      .then(resp => resp.json())
                      .then((packageJson) => {
                        console.log(packageJson.version);
                      });
                    

                    请记住,由于我们在这里专门讨论 package.json,因此该文件通常不会捆绑在您的生产构建中(甚至是开发版本),因此您必须使用 CopyWebpackPlugin 来使用 fetch 时可以访问它。

                    【讨论】:

                    • 不能。 Fetch 不支持本地文件...您可能正在使用 polyfill 或其他东西。
                    • @sapy 迟了几个月的回复,但 fetch API 绝对确实 支持从路径加载而不指定服务器的主机名,以及从相对路径加载。您正在考虑的是从file:/// URL 加载,这不是这里发生的情况。
                    • 这是一个非常有用的答案,非常简单,对我来说适用于本地文件
                    【解决方案18】:

                    我正在使用 babel+browserify,并且我在目录 ./i18n/locale-en.json 中有一个 JSON 文件,带有翻译命名空间(与 ngTranslate 一起使用)。

                    无需从 JSON 文件中导出任何内容(顺便说一句,这是不可能的),我可以使用以下语法对其内容进行默认导入:

                    import translationsJSON from './i18n/locale-en';
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-01-10
                      • 2019-07-24
                      • 1970-01-01
                      • 2018-02-14
                      • 2018-11-11
                      • 2018-11-25
                      • 2021-12-04
                      相关资源
                      最近更新 更多