Angular 5服务读取本地.json文件

131

我正在使用 Angular 5,使用 angular-cli 创建了一个服务。

我想创建一个服务,用于读取 Angular 5 中的本地 JSON 文件。

这是我的代码... 我有点卡住了...

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));

  }

}

我该如何完成这个任务?


1
例如,HttpClientModule 不应该在构造函数中注入。 - AT82
10个回答

183

首先,您需要注入 HttpClient 而不是 HttpClientModule, 第二件事是删除 .map((res:any) => res.json()),因为新的 HttpClient 默认会提供响应正文,最后确保您在 AppModule 中导入 HttpClientModule

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");
    }
}

将此添加到您的组件中:

@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);
        });
   }
}

1
我在这一行代码 "public getJSON(): Observable<any> {" 上遇到了 "未解决的类型Observable" 的问题。 - user8770372
1
最后一个问题...我如何从我的组件中获取这些数据? - user8770372
如果我想读取 JSON ID,我该怎么做?如果您不介意,请给我提供一个示例。 - user3669026
2
我在获取JSON文件时遇到了404错误...而且也要按照你们的流程进行操作。 - Nagender Pratap Chauhan
7
我收到了一条日志,内容为 GET http://localhost:4200/src/assets/data.json 404 (未找到),意思是请求本地服务器上的 src/assets/data.json 文件时遇到了 404 错误。 - Arefe
显示剩余3条评论

33

对于 Angular 7,我按照以下步骤直接导入 JSON 数据:

在 tsconfig.app.json 中:

"compilerOptions" 中添加 "resolveJsonModule": true

在服务或组件中:

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

然后

private example = exampleData;

22

你有另一种解决方案,直接导入你的json。

要编译,请在您的 typings.d.ts 文件中声明此模块。

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

在你的代码中

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

console.log(data_json)

假设我的 JSON 文件位于 assets/abc.json,且只使用一个模块 app.module.ts,那么如何在 typing.d.ts 中声明并导入它呢?请帮忙。 - Mahi
只需在您的 typing.d.ts 文件中声明模块。然后将您的 JSON 导入到您的类中。 - Nicolas Law-Dune
哪个模块?假设我在app.模块中使用它。ts? - Mahi
6
当我使用import { default as data_json } from '../../path_of_your.json';时,成功地使代码运行且没有错误。 - jonas
1
为什么我的控制台会显示“未定义(undefined)”? - Gromain
显示剩余3条评论

21

在寻找一种真正读取本地文件而不是从Web服务器读取文件(我更愿意称之为“远程文件”)的方法时,我发现了这个问题。

只需调用require

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

Angular-CLI的源代码启发了我:我发现他们通过将templateUrl属性替换为template并使用require调用实际的HTML资源来包含组件模板。

如果使用AOT编译器,您需要通过调整tsconfig.app.json添加节点类型定义:

"compilerOptions": {
  "types": ["node"],
  ...
},
...

3
为了使用require,我需要安装@types/node包,可以通过运行npm install @types/node --save-dev来完成,具体讨论请见这里 - jaycer
所有这些解决方案都很棒,但这是唯一一个允许我动态保存值和解析文件内容而无需初始导入的解决方案之一。 - Aaron Matthews

14
假设,您的项目的src/app文件夹中有一个名为data.json的文件,其中包含以下数值:
[
    {
        "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种读取本地JSON文件的方法

方法1:使用TypeScript 2.9+的import语句读取本地JSON文件

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);
  }
}

方法2:使用Angular HttpClient读取本地JSON文件

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;
    })
  }
}

方法三:使用 ES6+ import 语句在离线 Angular 应用中读取本地 JSON 文件

如果您的 Angular 应用程序离线,使用 HttpClient 读取 JSON 文件将失败。在这种情况下,我们还有一种方法可以使用支持导入 JSON 文件的 ES6+ import 语句来导入本地 JSON 文件。

但首先,我们需要添加一个类型文件,如下所示:

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

将以下代码添加到src/app文件夹下的新文件json-typings.d.ts中。

现在,您可以像TypeScript 2.9+一样导入JSON文件。

import * as data from "data.json";

1
在 tsconfig.app.json 文件中,需要在 "compilerOptions" 中添加 "resolveJsonModule": true。否则会出现错误,例如 - Consider using '--resolveJsonModule' to import module with '.json' extension - Pinaki

7
import data  from './data.json';
export class AppComponent  {
    json:any = data;
}

了解更多详情,请参阅此文章


对于我的本地文件来说,这是最容易使用的。我必须将 "allowSyntheticDefaultImports": true 添加到我的 tsconfig.json 的 'compilerOptions' 中,但只是为了解决 TypeScript 的 linting 错误,而不是实际错误。 - Rin and Len
这是解决方案:https://hackeruna.com/2020/04/27/error-with-angular-8-and-9-allowsyntheticdefaultimports-flag-error-ts1259/,用于此错误TS1259。 - juanitourquiza

6

试试这个

在你的服务中编写代码

import {Observable, of} from 'rxjs';

导入 JSON 文件

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

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

在组件中
get_products(){
    this.sharedService.getProduct().subscribe(res=>{
        console.log(res);
    })        
}

1
对于那些无法在tsconfig中添加“ resolveJsonModule”:true的人来说,这是目前最好的答案。 - soni

3
使用Typescript 3.6.3 和 Angular 6,对于我来说,这些解决方案都没有起作用。真正有效的方法是遵循这里的教程,该教程指出您需要将一个名为njson-typings.d.ts的小文件添加到您的项目中,其中包含以下内容:
declare module "*.json" {
  const value: any;
  export default value;
}

完成上述步骤后,我可以轻松导入我的硬编码JSON数据:

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

并在我的组件中使用它:

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

  constructor() {
    //  Load the data from a hardcoded .json file
    this.employees = employeeData;
    . . . .
  }

1

让我们创建一个JSON文件,我们将其命名为navbar.json,您可以随意命名!

navbar.json

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

现在我们已经创建了一个带有一些菜单数据的JSON文件。我们将进入应用组件文件并粘贴以下代码。

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;

}

现在您的Angular 7应用程序已准备好从本地JSON文件提供数据。请转到app.component.html并将以下代码粘贴到其中。

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>

0
对我来说,当我尝试导入数据文件时无法正常工作。相反,我将数据文件移动到资产文件夹,并尝试通过get请求访问它。
 public getProjectTree()
   {
      return this.http.get("assets/data.json");
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接