130

I am using Angular 5 and I've created a service using the angular-cli

What I want to do is to create a service that reads a local json file for Angular 5.

This is what I have ... I'm a bit stuck...

import { Injectable } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

@Injectable()
export class AppSettingsService {

  constructor(private http: HttpClientModule) {
    var obj;
    this.getJSON().subscribe(data => obj=data, error => console.log(error));
  }

  public getJSON(): Observable<any> {
    return this.http.get("./assets/mydata.json")
      .map((res:any) => res.json())
      .catch((error:any) => console.log(error));

  }

}

How can I get this finished?

dhilt
  • 18,707
  • 8
  • 70
  • 85
  • 1
    https://angular.io/tutorial/toh-pt6 For example, `HttpClientModule` should not be injected in constructor. – AT82 Nov 09 '17 at 16:30

10 Answers10

182

First You have to inject HttpClient and Not HttpClientModule, second thing you have to remove .map((res:any) => res.json()) you won't need it any more because the new HttpClient will give you the body of the response by default , finally make sure that you import HttpClientModule in your AppModule :

import { HttpClient } from '@angular/common/http'; 
import { Observable } from 'rxjs';

@Injectable()
export class AppSettingsService {

   constructor(private http: HttpClient) {
        this.getJSON().subscribe(data => {
            console.log(data);
        });
    }

    public getJSON(): Observable<any> {
        return this.http.get("./assets/mydata.json");
    }
}

to add this to your Component:

@Component({
    selector: 'mycmp',
    templateUrl: 'my.component.html',
    styleUrls: ['my.component.css']
})
export class MyComponent implements OnInit {
    constructor(
        private appSettingsService : AppSettingsService 
    ) { }

   ngOnInit(){
       this.appSettingsService.getJSON().subscribe(data => {
            console.log(data);
        });
   }
}
Chris Peacock
  • 4,107
  • 3
  • 26
  • 24
El houcine bougarfaoui
  • 35,805
  • 9
  • 37
  • 37
  • 1
    I'm getting "Unresolved Type Observable" ... on this line "public getJSON(): Observable {" –  Nov 09 '17 at 16:40
  • 1
    One last question ... How do I can this data from my component? –  Nov 09 '17 at 17:17
  • suppose if I want to read json id. What I have to do? Please if you dont mind provide me the example. – user3669026 Aug 30 '19 at 10:12
  • 2
    i have faced 404 error while fetching json file....and also follow same flow like yours.. – Nagender Pratap Chauhan Sep 27 '19 at 07:06
  • 7
    I receive 404 with the log `GET http://localhost:4200/src/assets/data.json 404 (Not Found)` – Arefe Aug 21 '21 at 12:21
  • Also include "import { AppSettingsService } from '../app-settings.service';" in the above Component file – Ansif Jul 05 '22 at 05:49
  • have you checked your code in prod environment..dont think we can read json or any file from asset folder like this. Code will work only on dev envrionemnt not prod.. ;) – lazydeveloper Nov 10 '22 at 18:23
  • those who get the 404, is mainly due to that there json file is not in assets folder, incase they you are required to move json file to any other directory then you need to add that in angular.json file – Wasit Shafi Aug 26 '23 at 05:18
31

For Angular 7, I followed these steps to directly import json data:

In tsconfig.app.json:

add "resolveJsonModule": true in "compilerOptions"

In a service or component:

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

And then

private example = exampleData;
jaycer
  • 2,941
  • 2
  • 26
  • 36
22

You have an alternative solution, importing directly your json.

To compile, declare this module in your typings.d.ts file

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

In your code

import { data_json } from '../../path_of_your.json';

console.log(data_json)
Nicolas Law-Dune
  • 1,631
  • 2
  • 13
  • 30
  • Suppose, I have my json in assets/abc.json, and using only one module app.module.ts then how to declare in typing.d.ts and how to import. Please help. – Mahi Nov 09 '17 at 18:53
  • Just declare the module in your typing.d.ts file. And import your JSON into your class – Nicolas Law-Dune Nov 10 '17 at 09:28
  • Which module? Suppose I am using it in app. module. ts? – Mahi Nov 10 '17 at 09:31
  • Second question, module "*.json"? You have written to declare what is this? Is this a module name? – Mahi Nov 10 '17 at 09:32
  • Hi. I'm getting `error TS2305: Module '"*.json"' has no exported member 'data_json'.` when I'm trying to use this solution. Webpack compiles succsessfully, but the error is thrown on execution. – jonas Nov 21 '17 at 10:06
  • 6
    I got this to work without errors when I did `import { default as data_json } from '../../path_of_your.json';` – jonas Nov 21 '17 at 11:12
  • Same solution with an extended explanation: https://hackernoon.com/import-json-into-typescript-8d465beded79 – LHSnow Jan 11 '18 at 13:04
  • 1
    Why am I getting "undefined" in the console? – Gromain Feb 28 '18 at 18:45
21

I found this question when looking for a way to really read a local file instead of reading a file from the web server, which I'd rather call a "remote file".

Just call require:

const content = require('../../path_of_your.json');

The Angular-CLI source code inspired me: I found out that they include component templates by replacing the templateUrl property by template and the value by a require call to the actual HTML resource.

If you use the AOT compiler you have to add the node type definitons by adjusting tsconfig.app.json:

"compilerOptions": {
  "types": ["node"],
  ...
},
...
fishbone
  • 3,140
  • 2
  • 37
  • 50
  • 3
    To use `require` I needed to install `@types/node` by running `npm install @types/node --save-dev` as discussed [here](https://stackoverflow.com/a/35961176/4463445) – jaycer Jan 24 '19 at 18:18
  • all these solutions are great, but this is one of the only ones that will allow me to save the values and parse the file content dynamically without an initial import – Aaron Matthews Dec 12 '19 at 13:41
14

Assumes, you have a data.json file in the src/app folder of your project with the following values:

[
    {
        "id": 1,
        "name": "Licensed Frozen Hat",
        "description": "Incidunt et magni est ut.",
        "price": "170.00",
        "imageUrl": "https://source.unsplash.com/1600x900/?product",
        "quantity": 56840
    },
    ...
]

3 Methods for Reading Local JSON Files

Method 1: Reading Local JSON Files Using TypeScript 2.9+ import Statement

import { Component, OnInit } from '@angular/core';
import * as data from './data.json';

@Component({
  selector: 'app-root',
  template: `<ul>
      <li *ngFor="let product of products">

      </li>
  </ul>`,
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'Angular Example';

  products: any = (data as any).default;

  constructor(){}
  ngOnInit(){
    console.log(data);
  }
}

Method 2: Reading Local JSON Files Using Angular HttpClient

import { Component, OnInit } from '@angular/core';
import { HttpClient } from "@angular/common/http";


@Component({
  selector: 'app-root',
  template: `<ul>
      <li *ngFor="let product of products">

      </li>
  </ul>`,
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'Angular Example';
  products: any = [];

  constructor(private httpClient: HttpClient){}
  ngOnInit(){
    this.httpClient.get("assets/data.json").subscribe(data =>{
      console.log(data);
      this.products = data;
    })
  }
}

Method 3: Reading Local JSON Files in Offline Angular Apps Using ES6+ import Statement

If your Angular application goes offline, reading the JSON file with HttpClient will fail. In this case, we have one more method to import local JSON files using the ES6+ import statement which supports importing JSON files.

But first we need to add a typing file as follows:

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

Add this inside a new file json-typings.d.ts file in the src/app folder.

Now, you can import JSON files just like TypeScript 2.9+.

import * as data from "data.json";
Abolfazl Roshanzamir
  • 12,730
  • 5
  • 63
  • 79
  • 1
    In tsconfig.app.json file, need to add `"resolveJsonModule": true` in "compilerOptions". otherwise there will be error like - `Consider using '--resolveJsonModule' to import module with '.json' extension` – Pinaki Mar 27 '22 at 07:18
7
import data  from './data.json';
export class AppComponent  {
    json:any = data;
}

See this article for more details.

Ole
  • 41,793
  • 59
  • 191
  • 359
  • For my local file this was easiest to use. I had to add `"allowSyntheticDefaultImports": true` to my tsconfig.json 'compilerOptions', but only to stop a linting error for TypeScript, NOT an actual error. – Rin and Len Dec 30 '19 at 13:13
  • This is the solution: https://hackeruna.com/2020/04/27/error-with-angular-8-and-9-allowsyntheticdefaultimports-flag-error-ts1259/ for this error TS1259 – juanitourquiza Apr 30 '20 at 23:31
6

Try This

Write code in your service

import {Observable, of} from 'rxjs';

import json file

import Product  from "./database/product.json";

getProduct(): Observable<any> {
   return of(Product).pipe(delay(1000));
}

In component

get_products(){
    this.sharedService.getProduct().subscribe(res=>{
        console.log(res);
    })        
}
  • 1
    Best answer to the moment for the ones that are not able to add "resolveJsonModule": true into their tsconfig – soni Jul 29 '19 at 15:27
3

Using Typescript 3.6.3, and Angular 6, none of these solutions worked for me.

What did work was to follow the tutorial here which says you need to add a small file called njson-typings.d.ts to your project, containing this:

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

Once this was done, I could simply import my hardcoded json data:

import employeeData from '../../assets/employees.json';

and use it in my component:

export class FetchDataComponent implements OnInit {
  public employees: Employee[];

  constructor() {
    //  Load the data from a hardcoded .json file
    this.employees = employeeData;
    . . . .
  }
Mike Gledhill
  • 27,846
  • 7
  • 149
  • 159
1

Let’s create a JSON file, we name it navbar.json you can name it whatever you want!

navbar.json

[
  {
    "href": "#",
    "text": "Home",
    "icon": ""
  },
  {
    "href": "#",
    "text": "Bundles",
    "icon": "",
    "children": [
      {
        "href": "#national",
        "text": "National",
        "icon": "assets/images/national.svg"
      }
    ]
  }
]

Now we’ve created a JSON file with some menu data. We’ll go to app component file and paste the below code.

app.component.ts

import { Component } from '@angular/core';
import menudata from './navbar.json';

@Component({
  selector: 'lm-navbar',
  templateUrl: './navbar.component.html'
})
export class NavbarComponent {
    mainmenu:any = menudata;

}

Now your Angular 7 app is ready to serve the data from the local JSON file.

Go to app.component.html and paste the following code in it.

app.component.html

<ul class="navbar-nav ml-auto">
                  <li class="nav-item" *ngFor="let menu of mainmenu">
                  <a class="nav-link" href="{{menu.href}}">{{menu.icon}} {{menu.text}}</a>
                  <ul class="sub_menu" *ngIf="menu.children && menu.children.length > 0"> 
                            <li *ngFor="let sub_menu of menu.children"><a class="nav-link" href="{{sub_menu.href}}"><img src="{{sub_menu.icon}}" class="nav-img" /> {{sub_menu.text}}</a></li> 
                        </ul>
                  </li>
                  </ul>
Surya R Praveen
  • 3,393
  • 1
  • 24
  • 25
0

For me, it didn't work when I try to import the data file. instead, I have moved the data file to the assets folder and tried to access it through get request.

 public getProjectTree()
   {
      return this.http.get("assets/data.json");
   }
Goutham Harshith
  • 238
  • 2
  • 16