67

So the code is simple:

calls.json

{"SERVER":{
    "requests":{
      "one":"1"
    }
} }

file.ts

import json = require('../static/calls.json');
console.log(json.SERVER);

the generated javascript is correct and when running the node js server, the console log json.SERVER prints '{ requests: { one: '1' } }', as it should.

The typescript compiler (commonjs) however, somehow does not particularly like this situation and throws: "Cannot find module '../static/calls.json'".

Ofcourse I tried writing a .d.ts file, like this:

declare module '../static/calls.json'{
    var exp:any;
    export = exp;
}

this then obviously throws: "Ambient module declaration cannot specify relative module name".

I also tried different variants, like:

declare module 'calls.json' {
    import * as json from '/private/static/calls.json';
    export = json;
}

and then requiring:

import json = require('calls.json');

None work properly and have their own little compiler errors :)

I want to use an external .json file because I use commonjs serverside and amd clientside and I want a single file for loading constants.

6 Answers 6

102

Use var instead of import.

var json = require('./calls.json');

You're loading a JSON file, not a module, so import shouldn't be used is this case. When var is used, require() is treated like a normal function again.

If you're using a Node.js definition, everything should just work, otherwise require will need to be defined.

Sign up to request clarification or add additional context in comments.

5 Comments

This would work, though I am using requirejs clientside. This means when loading the requirejs definition, the declared var require in the node definition causes problems because a var require was also declared in require.d.ts...
Yup, that's expected when both definitions are referenced at once. That would also be the case at runtime too. You would never be using both require at the same time. The quick solution is to have that file not reference either of them and just use declare var require: any;.
@thoughtrepo Could elaborate on your answer? Typescript to Babel to ES5 is still looking for a module. I'm finding myself in that situation, and although the fail-safe intuition would be to import the json as var config = require('./config.json'), Typescript-Babel does still indicate the same 'cannot find module .config.json' error message.
I got the error "Failed to lint:: require statement not part of an import statement". Can someone please help?
ts doesn't allow var.
37

TS 2.9 added support for well typed json imports. Just add:

{
  "compilerOptions": {
    "resolveJsonModule": true
  }
}

in your tsconfig.json or jsconfig.json. Now imports such as:

import json = require('../static/calls.json');

and

import * as json from '../static/calls.json';

should be resolved and have proper typings too!

4 Comments

Doesn't work see this github issue
@Max works for me. The fix was merged into master on the 5th of Jul, now available in stable.
this only works if your target is commonjs, if you want to output anything else it won't work
Works perfectly regardless of target. I and many others did have to restart VS Code for Intellisense to stop barking.
36

Another solution is to change data.json to data.ts and export like this

export default {
  "key" : {
    ...
  }
}

and import as you would expect:

import { default as data } from './data'

2 Comments

import { default as data } from './data.ts';
@phi not sure the '.ts' extension is needed.
21

This can also be done by using import statement if using webpack v2 which is already packed with json-loader.

Note that this is not async

import data from './data.json';//Note that this is not async

Also, in your typings.d.ts file add the following wildcard module to avoid typescript error saying: Cannot find module

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

For anyone interested in async imports, check this article by 2uality

Comments

3

As of Typescript 2.9 you can import JSON file natively without any additional hack/loader needed.

The following excerpt is copied from said link above.

...TypeScript is now able to import JSON files as input files when using the node strategy for moduleResolution. This means you can use json files as part of their project, and they’ll be well-typed!

./src/settings.json

{
    "dry": false,
    "debug": 

./src/foo.ts

import settings from "./settings.json";

settings.debug === true;  // Okay
settings.dry === 2;       // Error! Can't compare a `boolean` and `number`

Comments

-7
For Angular 6 it can work with simple HTTP get call as below

Service
//interface, could be Array , object 
export interface ResultJSON{

}
 //Read JSON file for 3DWide
  getJSON() {
    return this.http.get(this.filepathUrl);
  }

Component :import both service and interface and use as below
resultJSON :ResultJSON;
 this
      .testService
      .getJSON()
      .subscribe((data: ResultJSON) => {
           this.resultJSON= data;
           console.log(this.resultJSON); 


         });

1 Comment

requires unnecessary http request

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.