You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Angular中消费并解析Spring Boot HATEOAS API的嵌套响应

问题描述

从Spring Boot HATEOAS API收到嵌套JSON响应,需要提取其中的vehicleListingList数组,用于Angular组件的HTML模板渲染。现有代码直接将响应当作VehicleListing[]处理,导致无法正确遍历数据。

后端返回的JSON结构:

{
    "_embedded": {
        "vehicleListingList": [
            {
                "id": 1,
                "modelYear": "2022",
                "make": "Honda",
                "model": "Civic",
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/listings/1"
                    },
                    "vehicleListings": {
                        "href": "http://localhost:8080/listings"
                    }
                }
            },
            {
                "id": 2,
                "modelYear": "2017",
                "make": "Honda",
                "model": "CR-V",
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/listings/2"
                    },
                    "vehicleListings": {
                        "href": "http://localhost:8080/listings"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/listings"
        }
    }
}

现有app.component.ts代码:

import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { VehicleListing } from './vehicle-listing';
import { VehicleListingService } from './vehicle-listing.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  public responseObj: VehicleListing[];

  constructor(private listingService: VehicleListingService) {}

  ngOnInit() {
    this.getListings();
  }

  public getListings(): void {
    this.listingService.getListings().subscribe(
      (response: VehicleListing[]) => {
        this.responseObj = response;
        console.log(this.responseObj);
      },
      (error: HttpErrorResponse) => {
        alert(error.message);
      }
    );
  }
}
解决方案

1. 定义HATEOAS响应包装接口

创建接口匹配后端返回的完整嵌套结构,实现TypeScript类型校验:

// 可放在vehicle-listing.ts或单独文件中
export interface HateoasResponse {
  _embedded: {
    vehicleListingList: VehicleListing[];
  };
  _links: {
    self: { href: string };
  };
}

同时补全VehicleListing接口的所有字段(包括_links):

export interface VehicleListing {
  id: number;
  modelYear: string;
  make: string;
  model: string;
  _links: {
    self: { href: string };
    vehicleListings: { href: string };
  };
}

2. 调整组件内的数据解析逻辑

修改app.component.ts,将响应对象改为HateoasResponse类型,并提取嵌套的列表数据:

import { HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { VehicleListing, HateoasResponse } from './vehicle-listing';
import { VehicleListingService } from './vehicle-listing.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  public vehicleListings: VehicleListing[] = []; // 存储最终列表数据

  constructor(private listingService: VehicleListingService) {}

  ngOnInit() {
    this.getListings();
  }

  public getListings(): void {
    this.listingService.getListings().subscribe(
      (response: HateoasResponse) => {
        // 提取_embedded下的vehicleListingList数组
        this.vehicleListings = response._embedded.vehicleListingList;
        console.log(this.vehicleListings);
      },
      (error: HttpErrorResponse) => {
        alert(error.message);
      }
    );
  }
}

3. 更新服务的返回类型

调整VehicleListingService中的getListings方法,返回类型改为Observable<HateoasResponse>:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { HateoasResponse } from './vehicle-listing';

@Injectable({
  providedIn: 'root'
})
export class VehicleListingService {
  private apiUrl = 'http://localhost:8080/listings';

  constructor(private http: HttpClient) { }

  getListings(): Observable<HateoasResponse> {
    return this.http.get<HateoasResponse>(this.apiUrl);
  }
}

4. HTML模板渲染

在app.component.html中使用*ngFor遍历提取后的列表数据:

<div class="listing-container">
  <div *ngFor="let listing of vehicleListings" class="listing-card">
    <h3>{{ listing.make }} {{ listing.model }}</h3>
    <p>年份: {{ listing.modelYear }}</p>
    <p>ID: {{ listing.id }}</p>
    <a [href]="listing._links.self.href" target="_blank">查看详情</a>
  </div>
</div>

内容的提问来源于stack exchange,提问作者user14728486

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:05:23