【问题标题】:Importing JSON file in TypeScript在 TypeScript 中导入 JSON 文件
【发布时间】:2018-10-04 09:45:33
【问题描述】:

我有一个JSON 文件,如下所示:

{

  "primaryBright":    "#2DC6FB",
  "primaryMain":      "#05B4F0",
  "primaryDarker":    "#04A1D7",
  "primaryDarkest":   "#048FBE",

  "secondaryBright":  "#4CD2C0",
  "secondaryMain":    "#00BFA5",
  "secondaryDarker":  "#009884",
  "secondaryDarkest": "#007F6E",

  "tertiaryMain":     "#FA555A",
  "tertiaryDarker":   "#F93C42",
  "tertiaryDarkest":  "#F9232A",

  "darkGrey":         "#333333",
  "lightGrey":        "#777777"
}

我正在尝试将其导入.tsx 文件。为此,我将其添加到类型定义中:

declare module "*.json" {
  const value: any;
  export default value;
}

我正在像这样导入它。

import colors = require('../colors.json')

在文件中,我使用颜色primaryMain 作为colors.primaryMain。但是我得到一个错误:

类型 'typeof "*.json" 上不存在属性 'primaryMain'

【问题讨论】:

标签: json typescript


【解决方案1】:

在您的 TS 定义文件中,例如typings.d.ts`,你可以添加这一行:

declare module "*.json" {
const value: any;
export default value;
}

然后将其添加到您的 typescript(.ts) 文件中:-

import * as data from './colors.json';
const word = (<any>data).name;

【讨论】:

  • 这是个非常糟糕的主意。
  • 您介意解释一下为什么不好吗???我不是打字稿专家。 @AluanHaddad
  • 您的any 类型断言说明了两件事。 1)您只是根据定义在表面上错误地声明或导入。您应该从不在任何情况下都需要在您自己声明的模块的导入上放置类型断言。 2)即使你有一个疯狂的加载器在运行时以某种方式解决这个问题,上帝保佑,它仍然是访问给定形状的模块的一种疯狂的混乱和最脆弱的方式。 * as x fromx from 在运行时方面比 OP 中的更不匹配。真的不要这样做。
  • 感谢您的回复。我已经明白了。 @AluanHaddad
【解决方案2】:

导入表单和模块声明需要就模块的形状、导出的内容达成一致。

当您编写时(从 TypeScript 2.9 开始,在针对兼容的模块格式时导入 JSON 的次优做法参见注释

declare module "*.json" {
  const value: any;
  export default value;
}

您是说所有具有以.json 结尾的说明符的模块都有一个导出命名 default

您可以通过多种方式正确使用此类模块,包括

import a from "a.json";
a.primaryMain

import * as a from "a.json";
a.default.primaryMain

import {default as a} from "a.json";
a.primaryMain

import a = require("a.json");
a.default.primaryMain

第一种形式是最好的,它利用的语法糖正是 JavaScript 具有 default 导出的原因。

但是,我提到了其他形式,以提示您出了什么问题。特别注意最后一个。 require 给你一个代表模块本身的对象,不是它的导出绑定。

那么为什么会出错呢?因为你写了

import a = require("a.json");
a.primaryMain

但您的"*.json" 没有声明名为primaryMain 的导出。

所有这些都假设您的模块加载器按照您的原始声明的建议将 JSON 作为 default 导出提供。

注意: 自 TypeScript 2.9 起,您可以使用 --resolveJsonModule compiler flag 让 TypeScript 分析导入的 .json 文件并提供有关其形状的正确信息,从而无需通配符模块声明并验证文件的存在。某些目标模块格式不支持此功能。

【讨论】:

  • @Royi 这取决于你的装载机。对于远程文件,考虑使用await import('remotepath');
  • 继续滚动,下面有更多最新答案。
  • @jbmusso 我添加了一些关于 TypeScript 更高版本引入的改进的信息,但我认为这个答案并不过时,因为它是概念性的。不过,我愿意接受进一步改进的建议。
  • 风险在于,有些人可以简单地复制/粘贴您答案的第一行,只修复症状而不是根本原因。我相信@kentor 的答案会产生更多细节并提供更完整的答案。建议将您的注释移到您的答案之上,明确说明这是从今天开始解决此问题的正确方法。
  • @Atombit 它显然对很多人有用,包括我。在否决接受的答案之前,想解释什么不起作用?
【解决方案3】:

使用 TypeScript 2.9.+,您可以通过执行以下操作轻松导入具有类型安全和智能感知等优点的 JSON 文件:

import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes"
console.log(colorsJson.primaryBright);

确保将这些设置添加到您的tsconfig.json (documentation) 的compilerOptions 部分:

"resolveJsonModule": true,
"esModuleInterop": true,

旁注:

  • Typescript 2.9.0 有这个 JSON 功能的错误,它已在 2.9.2 中修复
  • esModuleInterop 仅对 colorsJson 的默认导入是必需的。如果将其设置为 false,则必须使用 import * as colorsJson from '../colors.json' 导入它

【讨论】:

  • 你不一定需要esModuleInterop,但你必须这样做import * as foo from './foo.json';——当我尝试启用它时,esModuleInterop 给我带来了其他问题。
  • 你说得对,我应该把它作为旁注添加:-)。
  • 注意:选项“resolveJsonModule”不能在没有“node”模块解析策略的情况下指定,所以你还需要将"moduleResolution": "node"放入你的tsconfig.json。它还有一个缺点,即您要导入的*.json 文件需要在"rootDir" 内。来源:blogs.msdn.microsoft.com/typescript/2018/05/31/…
  • @mpen 是正确的,但 import * as foo from './foo.json' 是错误的导入形式。不使用esModuleInterop时应该是import foo = require('./foo.json');
  • 我只需要"resolveJsonModule": true,一切都很好
【解决方案4】:

typescript 2.9+ 版本易于使用。因此,您可以轻松地将 JSON 文件导入为@kentor decribed

但如果您需要使用旧版本:

您可以通过更多 TypeScript 方式访问 JSON 文件。首先,确保您的新typings.d.ts 位置与tsconfig.json 文件中的include 属性相同。

如果您的 tsconfig.json 文件中没有包含属性。那么你的文件夹结构应该是这样的:

- app.ts
+ node_modules/
- package.json
- tsconfig.json
- typings.d.ts

但如果您的tsconfig.json 中有include 属性:

{
    "compilerOptions": {
    },
    "exclude"        : [
        "node_modules",
        "**/*spec.ts"
    ], "include"        : [
        "src/**/*"
    ]
}

那么您的typings.d.ts 应该位于src 目录中,如include 属性中所述

+ node_modules/
- package.json
- tsconfig.json
- src/
    - app.ts
    - typings.d.ts

在许多响应中,您可以为所有 JSON 文件定义一个全局声明。

declare module '*.json' {
    const value: any;
    export default value;
}

但我更喜欢这种类型更多的版本。例如,假设您有这样的配置文件config.json

{
    "address": "127.0.0.1",
    "port"   : 8080
}

然后我们可以为它声明一个特定的类型:

declare module 'config.json' {
    export const address: string;
    export const port: number;
}

很容易在你的打字稿文件中导入:

import * as Config from 'config.json';

export class SomeClass {
    public someMethod: void {
        console.log(Config.address);
        console.log(Config.port);
    }
}

但在编译阶段,您应该手动将 JSON 文件复制到您的 dist 文件夹。我只是在我的package.json 配置中添加了一个脚本属性:

{
    "name"   : "some project",
    "scripts": {
        "build": "rm -rf dist && tsc && cp src/config.json dist/"
    }
}

【讨论】:

  • rm -rf 是 Linux/Unix 的东西,还是在 ol'Windurz 上也能工作?
  • 谢谢,我的 typings.d.ts 不合适。一旦我移动到 /src,错误消息就消失了。
  • @Cody 这确实只是一个 Linux/Unix 的东西。
【解决方案5】:

另一种方法

const data: {[key: string]: any} = require('./data.json');

这是你仍然可以定义你想要的json类型并且不必使用通配符。

例如自定义类型json。

interface User {
  firstName: string;
  lastName: string;
  birthday: Date;
}
const user: User = require('./user.json');

【讨论】:

  • 这与问题无关,也是不好的做法。
  • 我这样做了,但我将日期作为字符串获取。我应该怎么做才能从 json 反序列化正确的日期对象?
【解决方案6】:

通常在 Node.js 应用程序中需要一个 .json。在 TypeScript 2.9 中,--resolveJsonModule 允许从 .json 文件导入、提取类型和生成。

示例#

// tsconfig.json

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

// .ts

import settings from "./settings.json";

settings.debug === true;  // OK
settings.dry === 2;  // Error: Operator '===' cannot be applied boolean and number


// settings.json

{
    "repo": "TypeScript",
    "dry": false,
    "debug": false
}
作者:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

【讨论】:

  • 这些是正确的compilerOptions - 像魅力一样工作
【解决方案7】:

tsconfig.json 文件中启用"resolveJsonModule": true 并按照以下代码实现,它对我有用:

const config = require('./config.json');

【讨论】:

    【解决方案8】:

    你应该添加

    "resolveJsonModule": true
    

    作为 tsconfig.json 的 compilerOptions 的一部分。

    【讨论】:

      【解决方案9】:

      下面是如何在运行时导入 json 文件

      import fs from 'fs'
      var dataArray = JSON.parse(fs.readFileSync('data.json', 'utf-8'))
      

      这样可以避免在导入大文件时出现 tsc 变慢或内存不足的问题,这在使用 resolveJsonModule 时可能发生。

      【讨论】:

        【解决方案10】:

        请注意,如果您使用@kentor ways

        确保在 tsconfig.json (documentation) 的 compilerOptions 部分添加这些设置:

        您需要在tsc 命令后面添加--resolveJsonModule--esModuleInterop 来编译您的TypeScript 文件。

        示例: tsc --resolveJsonModule --esModuleInterop main.ts

        【讨论】:

          【解决方案11】:

          在我的情况下,我必须更改:"include": ["src"]"include": ["."] 以及 "resolveJsonModule":true,因为我尝试从项目的根目录而不是从 ./src 导入 manifest.json

          【讨论】:

            【解决方案12】:

            在 Angular(打字稿)应用程序中,我需要在我的 environment.ts 中包含一个 .json 文件。为此,我必须在 tsconfig 中设置两个选项:

            {
              "compilerOptions": {
                "moduleResolution": "node",
                "resolveJsonModule": true
              }
            }
            

            然后,我可以将我的 json 文件导入到environment.ts

            import { default as someObjectName } from "../some-json-file.json";
            

            【讨论】:

              猜你喜欢
              • 2018-05-14
              • 2020-11-22
              • 2020-06-02
              • 2019-12-11
              • 2018-07-17
              • 2020-01-13
              • 2018-04-10
              • 2020-06-24
              相关资源
              最近更新 更多