Jak zaimportować plik JSON do pliku TypeScript?

86

Buduję aplikację mapową za pomocą Angular Maps i chcę zaimportować plik JSON jako listę markerów definiujących lokalizacje. Mam nadzieję, że użyję tego pliku JSON jako tablicy znaczników [] wewnątrz pliku app.component.ts. Zamiast definiować zakodowaną na stałe tablicę znaczników w pliku TypeScript.

Jaki jest najlepszy proces importowania tego pliku JSON do wykorzystania w moim projekcie? Doceniany każdy kierunek!

aonepathan
źródło
możesz zobaczyć moją odpowiedź, ponieważ dotyczy Angular 7+
Julian

Odpowiedzi:

115

Jedna linijka Aonepathana działała dla mnie aż do ostatniej aktualizacji maszynopisu.

Znalazłem Jecelyn Yeen za wpis , który sugeruje komentarz ten fragment do pliku definicji TS

dodaj plik typings.d.tsdo folderu głównego projektu z poniższą zawartością

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

a następnie zaimportuj swoje dane w ten sposób:

import * as data from './example.json';

aktualizacja lipiec 2019:

Typescript 2.9 ( docs ) wprowadził lepsze, inteligentniejsze rozwiązanie. Kroki:

  1. Dodaj resolveJsonModulewsparcie z tym wierszem w swoim tsconfig.jsonpliku:
"compilerOptions": {
    ...
    "resolveJsonModule": true
  }

instrukcja import może teraz zakładać domyślny eksport:

import data from './example.json';

a intellisense sprawdzi teraz plik json, aby zobaczyć, czy możesz użyć metod Array itp. całkiem fajne.

ryanrain
źródło
3
U mnie też to zadziałało - super zręcznie! UWAGA: Musisz zrestartować serwer deweloperski, aby to skompilowało się poprawnie.
Scott Byers
13
DostajęCannot find module '*.json'. Consider using '--resolveJsonModule' to import module with '.json' extensionts(2732)
Jeremy Thille
4
Musiałem również dodać, "esModuleInterop": true,jak określono w dokumentach maszynopisu, jednak mówią również, że należy używać commonjsjako modulezamiast esnext. Wydaje się, że to działa w przypadku obu. Czy jest jakiś powód, aby przejść na commonjs (jak wspomniano w dokumentacji), zamiast trzymać się domyślnego esnext?
timhc22
1
tak samo jak komentarze powyżej, których potrzebowałem "esModuleInterop":true. Również kod VS nadal pokazuje mi błąd ... ale wszystko działa dobrze
mikey
6
Musiałem dodać "allowSyntheticDefaultImports": truew compilerOptionsjak również ze świeżym Kątowymi 9.1.11 projektu.
yohosuff
28

Jak wspomniano w tym poście reddit , po Angular 7 możesz uprościć rzeczy do tych 2 kroków:

  1. Dodaj te trzy linie do compilerOptionsw swoim tsconfig.jsonpliku:
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
  1. Zaimportuj dane JSON:
import myData from '../assets/data/my-data.json';

I to wszystko. Możesz teraz używać myDataw swoich komponentach / usługach.

Julian
źródło
Do czego służy esModuleInterop?
giovannipds,
@giovannipds, to jest dla domyślnego importu json
Vasia Zaretskyi
25

Oto pełna odpowiedź dla Angular 6+ oparta na odpowiedzi @ryanrain:

Z angular-cli doc , json można traktować jako zasoby i uzyskiwać do niego dostęp ze standardowego importu bez użycia żądania Ajax.

Załóżmy, że dodajesz swoje pliki json do katalogu „your-json-dir”:

  1. dodaj „your-json-dir” do pliku angular.json (:

    "assets": [ "src/assets", "src/your-json-dir" ]

  2. utwórz lub edytuj plik typings.d.ts (w katalogu głównym projektu) i dodaj następującą zawartość:

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

    Umożliwi to import modułów „.json” bez błędu maszynopisu.

  3. w pliku kontrolera / usługi / czegokolwiek innego, po prostu zaimportuj plik, używając tej ścieżki względnej:

    import * as myJson from 'your-json-dir/your-json-file.json';

Benjamin Caure
źródło
3
A jeśli nie mam pliku typings.d.ts?
Kristopher Windsor
2
wtedy musisz utworzyć taki w katalogu głównym swojego projektu, zawierający tylko zawartość kroku 2
Benjamin Caure.
2
Ważna uwaga: dodaj niestandardowy plik do wpisywania do typeRoots w tsconfig.json "typeRoots": ["node_modules / @ types", "src / typings.d.ts"],
Japo Domingo
22

Dzięki za wkład, udało mi się znaleźć poprawkę, dodałem i zdefiniowałem json w górnej części pliku app.component.ts:

var json = require('./[yourFileNameHere].json');

To ostatecznie stworzyło markery i jest prostą linią kodu.

aonepathan
źródło
6
Zostałem error TS2304: Cannot find name 'require'.rozwiązany przez dodanie declare var require: any;, jak wyjaśniono w komentarzach zaakceptowanej odpowiedzi na pytanie stackoverflow.com/questions/43104114/… .
Ben
4
@Ben, musisz dodać typ węzła do swojego tsconfig. tj. "compilerOptions": { ... "types": ["node"] },tutaj jest powiązana odpowiedź dla tych, którzy jej potrzebują: stackoverflow.com/a/35961176/1754995
Kody
Cześć @aonepathan, mam nadzieję, że możesz mi pomóc: mam bibliotekę, która używa wymagania do odczytu pliku json. var json = require('./[yourFileNameHere]');bez rozszerzenia. W czasie kompilacji mam błąd: Module not found: Error: Can't resolve [yourFileNameHere] in [file name]czy masz pomysł na obejście tego problemu?
Neo1975
16

Pierwsze rozwiązanie - po prostu zmień rozszerzenie swojego pliku .json na .ts i dodaj export defaultna początku pliku, na przykład:

export default {
   property: value;
}

Następnie możesz po prostu zaimportować plik bez potrzeby dodawania tekstów, na przykład:

import data from 'data';

Drugie rozwiązanie pobierz plik json za pośrednictwem HttpClient.

Wstrzyknij HttpClient do swojego komponentu, na przykład:

export class AppComponent  {
  constructor(public http: HttpClient) {}
}

a następnie użyj tego kodu:

this.http.get('/your.json').subscribe(data => {
  this.results = data;
});

https://angular.io/guide/http

To rozwiązanie ma jedną wyraźną przewagę nad innymi rozwiązaniami przedstawionymi tutaj - nie wymaga przebudowy całej aplikacji, jeśli Twój json się zmieni (jest ładowany dynamicznie z oddzielnego pliku, więc możesz modyfikować tylko ten plik).

vicbyte
źródło
1
pierwsze rozwiązanie jest dobre, jeśli Twoje dane są statyczne i nie będą się zmieniać przez bardzo długi czas; zaoszczędzi ci to niepotrzebnych żądań http, ale jeśli te dane będą się ciągle zmieniać, skorzystaj z drugiego rozwiązania przesłanego przez serwer lub nawet rozważ dodanie go do bazy danych, jeśli zestaw danych jest ogromny
OzzyTheGiant
10

Przeczytałem niektóre odpowiedzi i wydawały się nie działać dla mnie. Używam Typescript 2.9.2, Angular 6 i próbuję zaimportować JSON w Jasmine Unit Test. Oto, co mi się udało.

Dodaj:

"resolveJsonModule": true,

Do tsconfig.json

Importuj jak:

import * as nameOfJson from 'path/to/file.json';

Przestań ng test, zacznij od nowa.

Źródła: https://blogs.msdn.microsoft.com/typescript/2018/05/31/announcing-typescript-2-9/#json-imports

Ian Jamieson
źródło
1
To było dla mnie najlepsze rozwiązanie. Nie jest potrzebny żaden plik z typami, a TS może rozwiązać nazwy właściwości za Ciebie.
Steve Hobbs
7

Dla Angular 7+,

1) dodaj plik „typings.d.ts” do folderu głównego projektu (np. Src / typings.d.ts):

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

2) importuj i uzyskuj dostęp do danych JSON:

import * as data from 'path/to/jsonData/example.json';
...
export class ExampleComponent {
    constructor() {
        console.log(data.default);
    }

}

lub:

import data from 'path/to/jsonData/example.json';
...
export class ExampleComponent {
    constructor() {
        console.log(data);
    }

}
Stevemaster92
źródło
data.default zawiesiła mnie. Dzięki za pełny przykład!
kevin_fitz
Uważaj na ścieżkę do swojego pliku json, ponieważ jest ona odpowiednia dla pliku, który importujesz, np. Jeśli masz usługę w src/app/services/folderze, a twój json jest w src/assets/data/folderze, musisz to określić jak../../assets/data/your.json
Adam Boczek
Działa doskonale, ale dlaczego potrzebny jest plik typings.d.ts?
robert
5

W angular7 po prostu użyłem

let routesObject = require('./routes.json');

Mój plik route.json wygląda następująco

{

    "routeEmployeeList":    "employee-list",
    "routeEmployeeDetail":      "employee/:id"
}

Dostęp do elementów JSON uzyskujesz za pomocą

routesObject.routeEmployeeList
Kodjo Tchioffo
źródło
Otóż ​​to! ;-) Wszystkie inne opcje są takie hakerskie! Jeśli masz TSLint, zgłosi reuqirebłąd - po prostu dodaj declare var require: any;na górze komponent klasy.
Pedro Ferreira
5

Od Typescript 2.9 można po prostu dodać:

"compilerOptions": {
    "resolveJsonModule": true
}

do tsconfig.json. Odtąd łatwo jest używać pliku json ( i będzie też ładne wnioskowanie o typie w VSCode):

data.json:

{
    "cases": [
        {
            "foo": "bar"
        }
    ]
}

W pliku Typescript:

import { cases } from './data.json';

Nigel Gilbert
źródło
2
let fs = require('fs');
let markers;
fs.readFile('./markers.json', handleJSONFile);

var handleJSONFile = function (err, data) {
   if (err) {
      throw err;
   }
   markers= JSON.parse(data);
 }
Fateh Mohamed
źródło
2

Kątowy 10

Zamiast tego powinieneś teraz edytować plik tsconfig.app.json(zwróć uwagę na „aplikację” w nazwie).

Tam znajdziesz compilerOptionsi po prostu dodaj resolveJsonModule: true.

Na przykład plik w zupełnie nowym projekcie powinien wyglądać tak:

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app",
    "types": [],
    "resolveJsonModule": true
  },
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}
Absay
źródło