How to read a JSON file in angular 6 - json

I created a project using angular cli [ version - 6.1.3 ] and was trying to import a JSON file in the component as -
import * as serverJson from '../../config/appdetails.json';
I wanted to include the following in the typings.d.ts -
declare module "*.json" {
const value: any;
export default value;
}
However, there is no typings.d.ts present in the project structure.
In such circumstance, what is the best way to import a JSON file in angular 6 ?

Just create typings.d.ts in that folder where yours JSON data is stored with this content:
declare module "*.json" {
const value: any;
export default value;
}
Then you can import your data in this manner, you need to name it, dont use '*':
import appDetails from '../../config/appdetails.json';

Related

Read JSON file from file in Angular

I have a JSON file config.json saved in the src/app/config directory.
[
"caseSensitive",
"matchKeywords",
"items"
]
I have to read the file and get the content of the JSON file without parsing it.
After searching for it, I got two ways
Add "resolveJsonModule": true to the tsconfig.json file
Declara a typing module declare module "*.json" {}
and importing JSON as
import * as data from './app/config/config.json';
export class SchemaService {
constructor() { }
getConfig() {
console.log('bool: ', data); // Output in screenshot
console.log('type: ', typeof BooleanData); // object
console.log('parsed: ', JSON.stringify(BooleanData));
}
}
But both the ways are giving the parsed output as
The JSON.stringify(BooleanData) statement is not giving the actual JSON file, instead, the array items are changed to key-value where the index is represented as key
{
"0":"caseSensitive",
"1":"matchKeywords",
"2":"items"
}
How can I read the raw JSON (without parsing) in Angular, or at least convert an object into JSON?
You can use a quickfix provide by #amer-yousuf But it will also let you import any .js file into your codebase as well. I wont prefer that. Here is an alternative approach
Define your config.json.ts (notice it ends with .ts and not .json) something like below
export const CONFIG = { // your JSON is assigned to CONFIG variable
"say": "hello world"
}
In your other .ts file where you want to use, use something like following code
import { CONFIG } from './config.json';
// ...
console.log(CONFIG.say);
// ...
Benefit of this method:
You can still use tslint/eslint on config.json.ts
Most editors will auto-complete for you
In Angular, to access the JSON as an object, you need to add the following two options to the tsconfig.json file:
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
Then you can import it within your service like the following:
import data from './app/config/config.json';
To access JSON as Module in Angular you should add these two lines into tsconfig.json file
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true
Then you can import it anywhere you want within the app
import * as Characters from './configs/characters.json';
Finaly access the object from module
export class CharactersComponent {
public characters: CharacterModel[] = (Characters as any).default;
}

How to import .json file with typescript React App

I'm getting the error:
Cannot find module '../public/data.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.
import "./styles.css";
import data from "../public/data.json";
/**
*
* Welcome to the DDS coding challenge.
*
* Load `/public/data.json` as if it were a GET endpoint
* and render it in a table using `/public/table.png` design.
*
* Make this behaviour reusable.
*
* Ask questions & have fun!
*
*/
export default function App() {
return <div className="App"></div>;
}
Here's a link to the challenge -> https://codesandbox.io/s/staging-snow-vvmvd?file=/src/App.tsx
The error message is letting you know that TypeScript cannot import JSON by default, you must enable the compiler option resolveJsonModule first. To do it in a React project, add the following to your tsconfig.json:
{
"compilerOptions": {
"resolveJsonModule": true
}
}
Next, when you import the JSON file, you must give it a path relative to the current file. The JSON file is going to be bundled with your JavaScript, so it should probably go in the /src directory instead of the /public directory. For example, if you put it in the same directory as App.tsx, then you would import it like so:
import data from "./data.json"
// data.json:
{
"greeting" : "xin chao Vietnam"
}
// component:
import * as data from 'data.json';
let greeting = data.greeting;
//registering jsonModule in tsconfig.json
"compilerOptions": {
....
"resolveJsonModule": true,
....
},
you can do import and define type of imported data at same time
e.g
const filters: {[key: string]: any} = require('./filters.json');

Import a local json file with Angular

I have a simple .json file outside of my project. Like this :
| common
| configuration.json
| angular-app
| src
| app
| my-component
| my-component.component.ts
| angular.json
In my-component.component.ts, i want to import configuration.json. I tried import configuration from '../../../../common.configuration.json' but Angular just keep throwing this error :
ERROR in src/app/record/record.component.ts(4,23): error TS2732: Cannot find module '../../../../common/configuration.json'. Consider using '--resolveJsonModule' to import module with '.json' extension
And when i try ng serve --resolveJsonModule, i got this error : Unknown option: '--resolveJsonModule'
I can't move configuration.json. The common directory is shared with other projects.
How do you import a local json file in an Angular project ?
If you're using typescript 2.9+ (Angular 6.1+), you can import JSON modules so it will get compiled into the application. Older version don't support this so that may be your issue.
All you need to do is make sure the following three compiler options are enabled in your tsconfig.json:
{
...
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
...
}
}
Then you can import JSON modules in any TS file:
import jsonContents from '../../contents.json';
I'm not exactly sure what you mean but I guess you want to use the config values in your component, right?
According to this tutorial this can be fixed by creating a type definition file json-typings.d.ts in your app root folder with the following contents:
declare module "*.json" {
const value: any;
export default value;
}
Try by using http call:
this.http.get(`yourpath/..../common/configuration.json`).subscribe((resp: any) => {
console.log(resp)
});

Importing JSON file in TypeScript

I have a JSON file that looks like following:
{
"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"
}
I'm trying to import it into a .tsx file. For this I added this to the type definition:
declare module "*.json" {
const value: any;
export default value;
}
And I'm importing it like this.
import colors = require('../colors.json')
And in the file, I use the color primaryMain as colors.primaryMain. However I get an error:
Property 'primaryMain' does not exist on type 'typeof "*.json"
With TypeScript 2.9.+ you can simply import JSON files with benefits like typesafety and intellisense by doing this:
import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes"
console.log(colorsJson.primaryBright);
Make sure to add these settings in the compilerOptions section of your tsconfig.json (documentation):
"resolveJsonModule": true,
"esModuleInterop": true,
Side notes:
Typescript 2.9.0 has a bug with this JSON feature, it was fixed with 2.9.2
The esModuleInterop is only necessary for the default import of the colorsJson. If you leave it set to false then you have to import it with import * as colorsJson from '../colors.json'
The import form and the module declaration need to agree about the shape of the module, about what it exports.
When you write (a suboptimal practice for importing JSON since TypeScript 2.9 when targeting compatible module formatssee note)
declare module "*.json" {
const value: any;
export default value;
}
You are stating that all modules that have a specifier ending in .json have a single export named default.
There are several ways you can correctly consume such a module including
import a from "a.json";
a.primaryMain
and
import * as a from "a.json";
a.default.primaryMain
and
import {default as a} from "a.json";
a.primaryMain
and
import a = require("a.json");
a.default.primaryMain
The first form is the best and the syntactic sugar it leverages is the very reason JavaScript has default exports.
However I mentioned the other forms to give you a hint about what's going wrong. Pay special attention to the last one. require gives you an object representing the module itself and not its exported bindings.
So why the error? Because you wrote
import a = require("a.json");
a.primaryMain
And yet there is no export named primaryMain declared by your "*.json".
All of this assumes that your module loader is providing the JSON as the default export as suggested by your original declaration.
Note: Since TypeScript 2.9, you can use the --resolveJsonModule compiler flag to have TypeScript analyze imported .json files and provide correct information regarding their shape obviating the need for a wildcard module declaration and validating the presence of the file. This is not supported for certain target module formats.
Here's how to import a json file at runtime
import fs from 'fs'
var dataArray = JSON.parse(fs.readFileSync('data.json', 'utf-8'))
This way you avoid issues with tsc slowing down or running out of memory when importing large files, which can happen when using resolveJsonModule.
It's easy to use typescript version 2.9+. So you can easily import JSON files as #kentor decribed.
But if you need to use older versions:
You can access JSON files in more TypeScript way. First, make sure your new typings.d.ts location is the same as with the include property in your tsconfig.json file.
If you don't have an include property in your tsconfig.json file. Then your folder structure should be like that:
- app.ts
+ node_modules/
- package.json
- tsconfig.json
- typings.d.ts
But if you have an include property in your tsconfig.json:
{
"compilerOptions": {
},
"exclude" : [
"node_modules",
"**/*spec.ts"
], "include" : [
"src/**/*"
]
}
Then your typings.d.ts should be in the src directory as described in include property
+ node_modules/
- package.json
- tsconfig.json
- src/
- app.ts
- typings.d.ts
As In many of the response, You can define a global declaration for all your JSON files.
declare module '*.json' {
const value: any;
export default value;
}
but I prefer a more typed version of this. For instance, let's say you have configuration file config.json like that:
{
"address": "127.0.0.1",
"port" : 8080
}
Then we can declare a specific type for it:
declare module 'config.json' {
export const address: string;
export const port: number;
}
It's easy to import in your typescript files:
import * as Config from 'config.json';
export class SomeClass {
public someMethod: void {
console.log(Config.address);
console.log(Config.port);
}
}
But in compilation phase, you should copy JSON files to your dist folder manually. I just add a script property to my package.json configuration:
{
"name" : "some project",
"scripts": {
"build": "rm -rf dist && tsc && cp src/config.json dist/"
}
}
In my case I needed to change tsconfig.node.json:
{
"compilerOptions": {
...
"resolveJsonModule": true
},
"include": [..., "colors.json"]
}
And to import like that:
import * as colors from './colors.json'
Or like that:
import colors from './colors.json'
with "esModuleInterop": true
You should add
"resolveJsonModule": true
as part of compilerOptions to tsconfig.json.
Often in Node.js applications a .json is needed. With TypeScript 2.9, --resolveJsonModule allows for importing, extracting types from and generating .json files.
Example #
// 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
}
by: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html
Another way to go
const data: {[key: string]: any} = require('./data.json');
This was you still can define json type is you want and don't have to use wildcard.
For example, custom type json.
interface User {
firstName: string;
lastName: string;
birthday: Date;
}
const user: User = require('./user.json');
In an Angular (typescript) app, I needed to include a .json file in my environment.ts. To do so, I had to set two options in tsconfig:
{
"compilerOptions": {
"moduleResolution": "node",
"resolveJsonModule": true
}
}
Then, I could import my json file into the environment.ts:
import { default as someObjectName } from "../some-json-file.json";
You can import a JSON file without modifying tsconfig you tell explicitly that you are importing JSON
import mydata from './mydataonfile.json' assert { type: "json" };
I know this does not fully answer the question but many people come here to know how to load JSON directly from a file.
Enable "resolveJsonModule": true in tsconfig.json file and implement as below code, it's work for me:
const config = require('./config.json');
Note that if you using #kentor ways
Make sure to add these settings in the compilerOptions section of your tsconfig.json (documentation):
You need to add --resolveJsonModule and--esModuleInterop behind tsc command to compile your TypeScript file.
Example:
tsc --resolveJsonModule --esModuleInterop main.ts
require is a common way to load a JSON file in Node.js
in my case I had to change: "include": ["src"] to "include": ["."] in addition to "resolveJsonModule":true because I tried to import manifest.json from the root of the project and not from ./src

ES 6 importing multiple default exports [duplicate]

I've noticed a few cases where I've seen something like the following:
// /reducers/reducer1.js
export default function reducer1(state = {}, action){
// etc...
}
// /reducers/reducer2.js
export default function reducer2(state = {}, action){
// etc...
}
// /reducers/index.js
import { combineReducers } from 'redux';
import reducer1 from './reducer1';
import reducer2 from './reducer2';
export default combineReducers({
reducer1,
reducer2
})
// /store.js
import masterReducer from './reducers';
export default function makeStore(){
// etc...
}
Notice the last "file" where we call import masterReducer from './reducers' - A few people seem to believe this should import the default export from the index.js file.
Is this actually part of the specification? - my interpretation/question is that this is the result of many folks using WebPack v1 which translates import statements into CommonJS-style requires statements? Or will this break in WebPack v2 with "official" import/export support?
Is this actually part of the specification?
No. How module identifiers ('./reducers' in your case) are resolved to the actual modules is left to the implementation of the module loader/bundler, it's not specificed by ES6. And it doesn't seem to be specified in CommonJs either.
This is just how node does it - when requiring a directory, it's index.js file will be used. Bundlers like browserify or webpack followed this convention (for compat reasons).