0

0

API 设计最佳实践:为何应避免直接返回列表,尤其混合类型列表

碧海醫心

碧海醫心

发布时间:2025-11-27 16:35:28

|

934人浏览过

|

来源于php中文网

原创

API 设计最佳实践:为何应避免直接返回列表,尤其混合类型列表

在 api 设计中,直接返回原始列表,特别是包含混合数据类型的列表,是一种应避免的实践。这种做法会破坏 api 的契约清晰性,导致消费者难以解析和理解响应数据,降低可扩展性和可维护性。推荐的做法是将列表封装在一个具有明确字段的自定义数据传输对象(dto)中,以确保强类型、清晰的结构和更好的兼容性。

在构建 RESTful API 时,我们经常需要返回一组同类型的数据。例如,一个返回电影评分的 API 可能最初设计为直接返回一个 Rating 对象的列表:

public class Rating {
    private Long movieId;
    private Integer rating;
    // ... 其他字段和getter/setter
}

其 API 响应可能如下所示:

[
  {"movieId": 5870, "rating": 5},
  {"movieId": 1234, "rating": 3}
]

这种设计在功能单一时看似简洁,但当业务需求演进,需要对 API 响应进行增强时,问题便会浮现。

直接返回混合类型列表的陷阱

假设现在需要为上述 API 增加一个字段,以指示这些评分属于哪个用户,例如“John Doe”。一种直观但极其不推荐的做法是尝试在现有列表中直接添加这个新信息:

@GetMapping("/ratings-with-user")
public List foo() {
    List finalList = new ArrayList<>();
    finalList.add(new Rating(5870L, 5));
    finalList.add(new Rating(1234L, 3));
    finalList.add("John Doe"); // 添加一个字符串类型的用户名称
    return finalList;
}

这样的 API 响应可能看起来像这样:

[
  {"movieId": 5870, "rating": 5},
  {"movieId": 1234, "rating": 3},
  "John Doe"
]

从技术上讲,Java 允许你返回 List,并且 JSON 序列化库也能够将其转换为上述 JSON 字符串。然而,这种做法在 API 设计中是一个严重的反模式,主要有以下几个问题:

TapNow
TapNow

新一代AI视觉创作引擎

下载
  1. 丧失类型契约与可预测性: 当 API 返回 List 时,消费者端无法通过简单的类型推断或现有数据模型来理解响应的结构。API 的核心价值在于提供一个明确的“契约”,说明它将返回什么类型的数据。List 破坏了这一契约,消费者无法确定列表中每个元素的具体类型和含义。
  2. 解析复杂性与脆弱性: 对于 List,JSON 解析器可以轻松地将其映射到 List 对象。但对于 [{"movieId":5870,"rating":5},{"movieId":1234,"rating":3},"John Doe"] 这种混合类型列表,标准的 JSON 解析库将无法直接将其映射到任何强类型集合。消费者不得不手动遍历列表,通过运行时类型检查(例如 instanceof 或检查 JSON 元素的结构)来判断每个元素是什么,并根据其位置(例如,假定用户名字总是在列表的最后一个位置)来提取信息。这种硬编码的解析逻辑非常脆弱,一旦 API 响应的顺序或类型发生微小变化,就可能导致客户端代码崩溃。
  3. 可扩展性差: 如果未来需要添加更多全局信息(例如,API 调用时间戳、分页元数据),或者用户名称可能变为一个更复杂的对象(如包含用户ID、姓名、头像URL),直接在 List 中添加会导致结构更加混乱,解析难度呈指数级增长。
  4. 调试与维护困难: 缺乏明确的数据结构使得 API 文档编写、测试和后续维护变得异常困难。新的开发者在不了解“隐藏知识”(如“John Doe”总是在最后一个位置)的情况下,难以理解和正确使用这个 API。

推荐的解决方案:封装在自定义对象中

为了解决上述问题,最佳实践是将列表以及任何相关的全局信息封装在一个专用的数据传输对象(DTO,Data Transfer Object)中。这个 DTO 将作为 API 的顶级响应对象,提供一个清晰、强类型的契约。

例如,我们可以创建一个 RatedActor 类来封装用户姓名和其评分列表:

public class RatedActor {
    private String name; // 用户的姓名
    private List ratings; // 该用户的评分列表

    public RatedActor(String name, List ratings) {
        this.name = name;
        this.ratings = ratings;
    }

    // ... getter/setter
}

然后,API 可以返回这个 RatedActor 对象:

@GetMapping("/ratings-for-actor")
public RatedActor getRatingsForActor() {
    List userRatings = new ArrayList<>();
    userRatings.add(new Rating(5870L, 5));
    userRatings.add(new Rating(1234L, 3));
    return new RatedActor("John Doe", userRatings);
}

此时的 API 响应将是:

{
  "name": "John Doe",
  "ratings": [
    {"movieId": 5870, "rating": 5},
    {"movieId": 1234, "rating": 3}
  ]
}

这种方法的优势

  1. 明确的 API 契约: 消费者清楚地知道 API 返回一个 RatedActor 对象,其中包含一个 name 字段和一个 ratings 列表。
  2. 强类型与易于解析: JSON 解析器可以直接将响应映射到 RatedActor 对象,无需手动解析或类型检查。这极大地简化了客户端代码。
  3. 良好的可扩展性: 如果未来需要添加更多与用户相关的全局信息(如 userId、profilePictureUrl),只需在 RatedActor 类中添加新字段即可,而不会破坏现有结构或客户端解析逻辑。
  4. 提高可读性和可维护性: 代码和 API 文档都更加清晰,新开发者能够更快地理解数据模型。
  5. 符合面向对象原则: 这种方式更好地利用了面向对象语言的数据建模能力,将相关数据封装在一个有意义的单元中。

总结

将 API 视为一个提供明确数据交换“契约”的接口至关重要。直接返回原始列表,尤其是包含混合数据类型的 List,会模糊这个契约,导致客户端难以理解、解析和维护。通过将列表和任何相关元数据封装在一个自定义的、强类型的数据传输对象(DTO)中,我们可以构建出更加健壮、可扩展、易于理解和使用的 API。这不仅是良好的编程实践,也是提升 API 质量和用户体验的关键一步。

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

834

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

739

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

735

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

397

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

399

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16926

2023.08.03

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.6万人学习

C# 教程
C# 教程

共94课时 | 6.9万人学习

Java 教程
Java 教程

共578课时 | 46.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号