Tìm kiếm trang web

Nhập tệp JSON trong TypeScript


Tôi có một tệp JSON trông như sau:

{

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

Tôi đang cố gắng nhập nó vào một tệp .tsx. Để làm điều này, tôi đã thêm cái này vào định nghĩa kiểu:

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

Và tôi đang nhập nó như thế này.

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

Và trong tệp, tôi sử dụng màu primaryMain như colors.primaryMain. Tuy nhiên, tôi nhận được lỗi:

Thuộc tính 'primaryMain' không tồn tại trên kiểu 'typeof "*.json"'

Câu trả lời #1

Với TypeScript 2.9 trở lên, bạn có thể đơn giản nhập các tệp JSON với các lợi ích như an toàn kiểu và intellisense bằng cách thực hiện như sau:

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

Hãy chắc chắn thêm các cài đặt này vào phần compilerOptions trong tsconfig.json của bạn (tài liệu):

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

Ghi chú bên lề:

  • Typescript 2.9.0 có một lỗi với tính năng JSON này, nó đã được sửa trong phiên bản 2.9.2
  • esModuleInterop chỉ cần thiết cho việc nhập khẩu mặc định của colorsJson. Nếu bạn để nó là false thì bạn phải nhập khẩu nó bằng import * as colorsJson from '../colors.json'

Câu trả lời #2

Biểu mẫu nhập khẩu và khai báo mô-đun cần đồng ý về hình thức của mô-đun, về những gì nó xuất khẩu.

Khi bạn viết (một thực hành không tối ưu để nhập JSON kể từ TypeScript 2.9 khi nhắm vào các định dạng mô-đun tương thíchxem ghi chú)

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

Bạn đang nói rằng tất cả các mô-đun có chỉ định kết thúc bằng .json đều có một xuất khẩu có tên là default.

Có nhiều cách bạn có thể sử dụng đúng một mô-đun như vậy bao gồm

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

và

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

và

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

và

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

Hình thức đầu tiên là tốt nhất và cú pháp ngọt ngào mà nó tận dụng chính là lý do JavaScript có các xuất khẩu default.

Tuy nhiên tôi đã đề cập đến các hình thức khác để gợi ý cho bạn về những gì đang xảy ra sai. Hãy chú ý đặc biệt đến cái cuối cùng. require cung cấp cho bạn một đối tượng đại diện cho chính module và không phải các liên kết được xuất khẩu của nó.

Vậy tại sao lại có lỗi? Bởi vì bạn đã viết

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

Và vẫn không có xuất nào có tên primaryMain được khai báo bởi "*.json" của bạn.

Tất cả điều này giả định rằng trình tải module của bạn đang cung cấp JSON như là xuất khẩu default như đã được đề xuất trong khai báo ban đầu của bạn.

Lưu ý: Kể từ TypeScript 2.9, bạn có thể sử dụng cờ trình biên dịch --resolveJsonModule để TypeScript phân tích các tệp .json được nhập và cung cấp thông tin chính xác về cấu trúc của chúng, loại bỏ nhu cầu khai báo mô-đun đại diện và xác thực sự tồn tại của tệp. Điều này không được hỗ trợ cho một số định dạng mô-đun mục tiêu nhất định.

Câu trả lời #3

Đây là cách nhập một tệp json vào thời gian chạy

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

Bằng cách này, bạn tránh được các vấn đề khi tsc chạy chậm hoặc hết bộ nhớ khi nhập các tệp lớn, điều này có thể xảy ra khi sử dụng resolveJsonModule.

Câu trả lời #4

Trong trường hợp của tôi, tôi cần thay đổi tsconfig.node.json:

{
  "compilerOptions": {
    ...
    "resolveJsonModule": true
  },
  "include": [..., "colors.json"]
}

Và để nhập khẩu như thế:

import * as colors from './colors.json'

Hoặc như vậy:

import colors from './colors.json'

với "esModuleInterop": true

Câu trả lời số 5

Rất dễ dàng sử dụng phiên bản TypeScript 2.9+. Vì vậy, bạn có thể dễ dàng nhập các tệp JSON như @kentor đã mô tả.

Nhưng nếu bạn cần sử dụng các phiên bản cũ hơn:

Bạn có thể truy cập các tệp JSON theo cách TypeScript hơn. Trước tiên, hãy đảm bảo vị trí mới của typings.d.ts giống với thuộc tính include trong tệp tsconfig.json của bạn.

Nếu bạn không có thuộc tính include trong tệp tsconfig.json của mình. Thì cấu trúc thư mục của bạn nên như sau:

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

Nhưng nếu bạn có một thuộc tính include trong tsconfig.json của bạn:

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

Sau đó typings.d.ts của bạn nên nằm trong thư mục src như được mô tả trong thuộc tính include

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

Như trong nhiều phản hồi, bạn có thể định nghĩa một khai báo toàn cục cho tất cả các tệp JSON của mình.

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

nhưng tôi thích một phiên bản có kiểu hơn của điều này. Ví dụ, giả sử bạn có tệp cấu hình config.json như sau:

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

Sau đó chúng ta có thể khai báo một loại cụ thể cho nó:

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

Việc nhập vào các tệp TypeScript của bạn rất dễ dàng:

import * as Config from 'config.json';

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

Nhưng trong giai đoạn biên dịch, bạn nên sao chép các tệp JSON vào thư mục dist của bạn một cách thủ công. Tôi chỉ thêm một thuộc tính script vào cấu hình package.json của mình:

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

Câu trả lời số 6

Trong một ứng dụng Angular (typescript), tôi cần bao gồm một tệp .json trong environment.ts của mình. Để làm điều đó, tôi phải đặt hai tùy chọn trong tsconfig:

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

Sau đó, tôi có thể nhập tệp json của mình vào environment.ts:

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

Câu trả lời số 7

Thường trong các ứng dụng Node.js cần một tệp .json. Với TypeScript 2.9, --resolveJsonModule cho phép nhập khẩu, trích xuất kiểu dữ liệu từ và tạo các tệp .json.

Ví dụ #

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

bởi: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

Câu trả lời số 8

Bạn nên thêm

"resolveJsonModule": true

như một phần của compilerOptions trong tsconfig.json.

Câu trả lời số 9

Bạn có thể nhập tệp JSON mà không cần chỉnh sửa tsconfig bằng cách chỉ định rõ ràng rằng bạn đang nhập JSON

import mydata  from './mydataonfile.json' assert { type: "json" };

Tôi biết điều này không trả lời đầy đủ câu hỏi nhưng nhiều người đến đây để biết cách tải JSON trực tiếp từ một tập tin.

Câu trả lời số 10

TypeScript 5.3 đã giới thiệu Thuộc tính Nhập khẩu, trước đây được gọi là Khẳng định Nhập khẩu, có thể cung cấp thông tin về định dạng mong đợi của một mô-đun được nhập tại thời gian chạy.

Thuộc tính Import đảm bảo rằng một mô-đun được nhập với định dạng chính xác. Điều đó có nghĩa là một tệp .json thực sự chứa mã JavaScript có thể chạy sẽ chắc chắn được hiểu là JSON.

import colors from "./colors.json" with { type: "json" };

Bài viết liên quan