139

I am building a map application using Angular Maps and want to import a JSON file as a list of markers defining locations. I'm hoping to use this JSON file as marker[] array inside the app.component.ts . Instead of defining a hardcoded array of markers inside the TypeScript file.

What is the best process of importing this JSON file for use in my project? Any direction greatly appreciated!

aonepathan
  • 1,845
  • 2
  • 13
  • 15

12 Answers12

207

Aonepathan's one-liner was working for me until a recent typescript update.

I found Jecelyn Yeen's post which suggests posting this snippet into your TS Definition file

add file typings.d.ts to the project's root folder with below content

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

and then import your data like this:

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

update July 2019:

Typescript 2.9 (docs) introduced a better, smarter solution. Steps:

  1. Add resolveJsonModule support with this line in your tsconfig.json file:
"compilerOptions": {
    ...
    "resolveJsonModule": true
  }

the import statement can now assumes a default export:

import data from './example.json';

and intellisense will now check the json file to see whether you can use Array etc. methods. pretty cool.

ryanrain
  • 4,473
  • 3
  • 21
  • 21
  • This method worked for me and seems to be the cleanest and most direct way to solving the problem. – Jason Van Der Meijden Apr 11 '18 at 13:04
  • 3
    This worked for me as well - super slick! NOTE: You need to restart your dev server for this to compile correctly. – Scott Byers Apr 30 '18 at 21:29
  • 1
    @RossRawlins restart your project. – Emeric Dec 09 '18 at 11:28
  • import * as data from './example.json'; and subscribing json which one is preferred and why to subscribe if we can import directly? – Mahi Jan 18 '19 at 18:07
  • Thank you for the link. The article has been updated to work with typescript 2.9+ – Anup Sharma May 10 '19 at 12:41
  • 17
    I'm getting `Cannot find module '*.json'. Consider using '--resolveJsonModule' to import module with '.json' extensionts(2732)` – Jeremy Thille May 26 '19 at 15:39
  • 9
    I needed to also add `"esModuleInterop": true,` as specified in the typescript docs, however they also say to use `commonjs` as the `module` instead of `esnext`. This seems to work with either. Is there any reason to switch to commonjs (as mentioned in the docs) as oppose to stick with the default of esnext? – timhc22 Oct 29 '19 at 16:09
  • 2
    same as comments above I needed `"esModuleInterop":true`. Also VS code still is showing me an error.. but everything works fine – mikey Mar 11 '20 at 03:45
  • 9
    I had to add `"allowSyntheticDefaultImports": true` in the `compilerOptions` as well with a fresh Angular 9.1.11 project. – yohosuff Jun 19 '20 at 21:56
  • 1
    restarting VS Code got rid of the error `Consider using '--resolveJsonModule'`for me. – Touré Holder Jun 24 '20 at 01:02
  • 2
    This change break the `import * as moment from 'moment'` statement. Changing it to `import moment from 'moment'` worked. Also, VS Code restart was required. – matrix Oct 28 '20 at 17:51
  • Thank you for this! – Carlo Nyte May 19 '21 at 17:47
  • While importing a JSON file works, this should be considered an **anti-pattern**, since data does **not** belong together with the code. If your JSON file is more than a couple of kilobytes then you will be better off using [HttpClient](https://angular.io/guide/http) — apart from separating data and code, this will also allow you to have a progress loader and a fluid UI if your data is big. – ccpizza Aug 16 '21 at 12:29
  • it is returning undefined – Tanmay Bairagi Oct 13 '21 at 05:45
68

As stated in this reddit post, after Angular 7, you can simplify things to these 2 steps:

  1. Add those three lines to compilerOptions in your tsconfig.json file:
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
  1. Import your json data:
import myData from '../assets/data/my-data.json';

And that's it. You can now use myDatain your components/services.

Yulian
  • 6,262
  • 10
  • 65
  • 92
31

Thanks for the input guys, I was able to find the fix, I added and defined the json on top of the app.component.ts file:

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

This ultimately produced the markers and is a simple line of code.

aonepathan
  • 1,845
  • 2
  • 13
  • 15
  • 7
    I got `error TS2304: Cannot find name 'require'.` Solved by adding `declare var require: any;`, as explained in comments of accepted answer for question https://stackoverflow.com/questions/43104114/cannot-find-name-require-after-upgrading-to-angular4/43122829. – Ben Mar 30 '18 at 19:16
  • 4
    @Ben, you need to add the node type to your tsconfig. i.e. `"compilerOptions": { ... "types": ["node"] },` Here is the related answer for those who require it: https://stackoverflow.com/a/35961176/1754995 – Kody Aug 09 '19 at 16:47
  • Hi @aonepathan, I hope you can help me: I have a library that use require to read a json file. `var json = require('./[yourFileNameHere]');` without the extension. At compile time I have an error: `Module not found: Error: Can't resolve [yourFileNameHere] in [file name]` do you have any idea to bypass this issue? – Neo1975 Jul 21 '20 at 06:48
26

Here is complete answer for Angular 6+ based on @ryanrain answer:

From angular-cli doc, json can be considered as assets and accessed from standard import without use of ajax request.

Let's suppose you add your json files into "your-json-dir" directory:

  1. add "your-json-dir" into angular.json file (:

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

  2. create or edit typings.d.ts file (at your project root) and add the following content:

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

    This will allow import of ".json" modules without typescript error.

  3. in your controller/service/anything else file, simply import the file by using this relative path:

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

Benjamin Caure
  • 2,090
  • 20
  • 27
18

First solution - simply change the extension of your .json file to .ts and add export default at the beginning of the file, like so:

export default {
   property: value;
}

Then you can just simply import the file without the need to add typings, like so:

import data from 'data';

Second solution get the json via HttpClient.

Inject HttpClient into your component, like so:

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

and then use this code:

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

https://angular.io/guide/http

This solution has one clear adventage over other solutions provided here - it doesn't require you to rebuild entire application if your json will change (it's loaded dynamically from a separate file, so you can modify only that file).

vicbyte
  • 3,690
  • 1
  • 11
  • 20
  • 2
    first solution is good if your data is static and will not change for a very long time; it will save you unnecessary http requests, but if this data changes constantly, then use the second solution sent by server or even consider adding it to a database if the data set is huge – OzzyTheGiant Jan 16 '19 at 21:32
15

I had read some of the responses and they didn't seem to work for me. I am using Typescript 2.9.2, Angular 6 and trying to import JSON in a Jasmine Unit Test. This is what did the trick for me.

Add:

"resolveJsonModule": true,

To tsconfig.json

Import like:

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

Stop ng test, start again.

Reference: https://blogs.msdn.microsoft.com/typescript/2018/05/31/announcing-typescript-2-9/#json-imports

Ian Jamieson
  • 4,376
  • 2
  • 35
  • 55
11

As of Typescript 2.9, one can simply add:

"compilerOptions": {
    "resolveJsonModule": true
}

to the tsconfig.json. Thereafter, it's easy to use a json file (and there will be nice type inference in VSCode, too):

data.json:

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

In your Typescript file:

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

Nigel Gilbert
  • 439
  • 5
  • 5
11

Angular 10

You should now edit the tsconfig.app.json (notice the "app" in the name) file instead.

There you'll find the compilerOptions, and you simply add resolveJsonModule: true.

So, for example, the file in a brand new project should look like this:

/* 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
  • 111
  • 1
  • 3
8

For Angular 7+,

1) add a file "typings.d.ts" to the project's root folder (e.g., src/typings.d.ts):

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

2) import and access JSON data either:

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

}

or:

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

}
Stevemaster92
  • 256
  • 3
  • 6
  • data.default was hanging me up. Thanks for the full example! – kevin_fitz Dec 21 '18 at 18:53
  • Be careful about the path to your json file because it's relevant to the file you import the file e.g. if you have a service in `src/app/services/` folder and your json is in `src/assets/data/` folder you have to specify it like `../../assets/data/your.json` – Adam Bogdan Boczek Jan 11 '19 at 15:21
  • It work perfectly, but why typings.d.ts file is needed? – robert Mar 22 '19 at 21:36
6

In angular7, I simply used

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

My routes.json file looks like this

{

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

You access json items using

routesObject.routeEmployeeList
Kodjo Tchioffo
  • 421
  • 6
  • 6
  • That's it! ;-) All the other options are so hacky! If you have TSLint will throw a `reuqire` error - just add `declare var require: any;` on top of the class component. – Pedro Ferreira Mar 27 '19 at 18:13
5

I couldn't import a different file.json too. But I resolved it like this

const swaggerDoc = require('../swagger.json')
jorge
  • 109
  • 1
  • 2
3
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
  • 20,445
  • 5
  • 43
  • 52