Angular 4升级至Angular 5时AuthService中json()方法报错咨询
解决Angular 4升级到5时AuthService的JSON解析错误
嘿,这个问题我太熟悉了!你遇到的是Angular 5里HttpClient和老版本Http的核心差异,加上一个容易忽略的HttpHeaders使用坑,我帮你一步步解决:
核心错误原因
Angular 5引入的@angular/common/http里的HttpClient,默认会自动将响应体解析为JSON对象,不再需要像老版本Http那样手动调用.json()方法——这就是你收到Property 'json' does not exist on type 'Object'错误的原因。
另外还有一个隐藏问题:你当前的HttpHeaders写法是无效的,因为HttpHeaders是不可变对象,每次调用append()都会返回一个新的实例,而不是修改原对象,所以你的请求头其实根本没加上授权信息!
具体修改步骤
1. 移除.json()调用
把报错的这行:
user = resp.json().principal;
改成直接访问响应对象的属性:
user = resp['principal']; // 要是想更严谨,可以定义响应类型接口,比如: // interface LoginResponse { principal: User }; // user = (resp as LoginResponse).principal;
2. 修复HttpHeaders的赋值方式
原来的headers创建代码不会生效,改成链式调用(每次append都会返回新的headers实例):
const base64Credential: string = btoa(`${user.username}:${user.password}`); const headers = new HttpHeaders() .append('Accept', 'application/json') .append('Authorization', `Basic ${base64Credential}`);
3. 补充:让请求真正执行(可选但关键)
你的logIn方法里调用了http.get()但没有返回Observable也没有订阅,这样请求根本不会发送!建议改成返回Observable,让组件去订阅触发请求:
public logIn(user: User): Observable<User> { // ... 上面的headers代码 ... return this.http.get('http://localhost:8081/account/login', { headers: headers}).pipe( map(resp => { user = resp['principal']; if (user) { localStorage.setItem('currentUser', JSON.stringify(user)); } return user; }) ); }
注:Angular 5对应的RxJS版本推荐用pipe()包裹操作符,替代旧的链式调用写法,更符合新版本规范。
修改后的完整AuthService代码
import { Injectable } from '@angular/core'; import { User } from '../model/model.user'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class AuthService { constructor(public http: HttpClient) { } public logIn(user: User): Observable<User> { const base64Credential: string = btoa(`${user.username}:${user.password}`); const headers = new HttpHeaders() .append('Accept', 'application/json') .append('Authorization', `Basic ${base64Credential}`); return this.http.get('http://localhost:8081/account/login', { headers: headers}).pipe( map(resp => { // 直接使用resp,HttpClient已自动解析JSON const loggedInUser = resp['principal'] as User; if (loggedInUser) { localStorage.setItem('currentUser', JSON.stringify(loggedInUser)); } return loggedInUser; }) ); } logOut(): Observable<any> { return this.http.post('http://localhost:8081/logout', {}).pipe( map(resp => { localStorage.removeItem('currentUser'); return resp; }) ); } }
额外说明
- 如果需要处理非JSON响应,可以在
http.get()的选项里添加responseType: 'text'等配置,不过你的接口返回JSON,默认配置就够用。 - 关于RxJS操作符:Angular 5之后推荐用
pipe()组合操作符,这是RxJS 6+的标准写法,兼容性更好。
内容的提问来源于stack exchange,提问作者SS_FStuck
相关产品推荐
相关产品推荐

