13

In my Angular project I'm importing JSON files for my own little localization service. I'm using the method suggested here, updating my typings.d.ts to

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

This worked fine for Angular 6, but after the update to Angular 7 my imports seem to be undefined when I try to access a property.

import * as de from './strings/de.json';
import * as en from './strings/en.json';

var s = en["mykey"]

The JSON has a very simple key => value structure:

{
  "myKey": "My Headline",
  …
}

What has changed between 6.1 & 7 that could lead to this behaviour?

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Thomas
  • 4,030
  • 4
  • 40
  • 79
  • Can you share the `en.json` content format ? – ibenjelloun Oct 19 '18 at 08:18
  • I've added it to the question – Thomas Oct 19 '18 at 08:19
  • `en["mykey"]` is undefined but what about `en`, what's its value ? – ibenjelloun Oct 19 '18 at 08:24
  • Interestingly on closer inspection it seems that all values have been wrapped inside a new 'default'-object. Any ideas where this could be comming from? – Thomas Oct 19 '18 at 08:31
  • 1
    Did you check the typescript version coming with Angular 7? Maybe there is something. – jbin Oct 19 '18 at 08:39
  • Angular 7 comes with typescript 3.1 : https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes didn't notice anything that would break imports from typescript 2.9 (Angular 6) to typescript 3.1 – ibenjelloun Oct 19 '18 at 08:41
  • I feel like this part could be an indicator, although I don't really understand it completely https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#under-allowsyntheticdefaultimports-types-for-default-imports-are-synthesized-less-often-for-ts-and-js-files – Thomas Oct 19 '18 at 09:00

4 Answers4

20

Turns out with Angular 7 & TypeScript 3.1 there actually have been some changes (I guess they have been there since TS 2.9+?). Using the code in the question, all values are wrapped inside a 'default'-object. To prevent this I had to simplify the import statements:

import de from './strings/de.json';
import en from './strings/en.json';

Also see this question for more details on how to import JSON files in TypeScript.

Thomas
  • 4,030
  • 4
  • 40
  • 79
13

After a lot of digging and trail and error, I finally got my app to import JSON correctly in Angular 7:

  1. Firstly, remove

    "resolveJsonModule": true
    "esModuleInterop": true
    

    from tsconfig.json, if you have that in there from other non-Angular 7 specific answers.

  2. Create src/typings.d.ts:

    declare module "*.json" {
      const value: any;
      export default value;
    }
    
  3. Update typeRoots in tsconfig.json to use src/typings.d.ts, e.g:

    "typeRoots": [
      "node_modules/@types",
      "src/typings.d.ts"
    ],
    
  4. Import JSON:

    import data from './data.json';
    console.log(data);
    
Greg Brown
  • 1,251
  • 1
  • 15
  • 32
  • 1
    It should be noted that this is not necessary for importing into a component. It only seems necessary for importing into a service (or like entity?). – Software Prophets Mar 13 '19 at 21:05
7

In Angular 7 I had to take these steps:

(1) imports

import pkg from '../../package.json'

(2) tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    AND more compiler options here
  }
}

(3) angular.json (to stop ng lint breaking on JSON imports)

The only change here is to add ... "**/*.json"

"lint": {
  "builder": "@angular-devkit/build-angular:tslint",
  "options": {
    "tsConfig": [
      "src/tsconfig.app.json",
      "src/tsconfig.spec.json"
    ],
    "exclude": [
      "**/node_modules/**",
      "**/*.json"
    ]
  }
}
danday74
  • 52,471
  • 49
  • 232
  • 283
  • 1
    using import * from * without setting "allowSyntheticDefaultImports" to true in the tsconfig.json file would lead to errors, the above instruction as to go about is, however, valid, take note – Seyi Daniels Jul 01 '19 at 07:42
0

I was looking for a solution that would work without me tinkering with the angular.json file

I solved it by exporting my JSON as a .ts constant:

export const TEST_DATA = {...};

and then import it to my components

Jakub
  • 479
  • 5
  • 17