在 Spring Boot 中如何处理请求体中的可选字段?

发布: (2025年12月26日 GMT+8 16:48)
7 min read
原文: Dev.to

Source: Dev.to

想象一下在网上填写注册表单。
用户名密码 这样的字段是必填的,而 个人简介偏好设置 之类的字段则是可选的。
你不会因为跳过了可选字段就让表单提交失败——对吧?

同样的思路也适用于 REST API。当客户端发送请求体时,并不是每个字段都必须存在。了解 在 Spring Boot 中如何处理请求体中的可选字段 对于构建 灵活、向后兼容且对初学者友好的 API 至关重要。

在本篇博客中,你将一步步学习这一概念,使用 通俗易懂的语言、贴近实际的类比,以及完整的端到端示例(包括 cURL 请求和响应)

Source:

核心概念

请求体中的可选字段是什么?

可选字段是 JSON 属性,它们:

  • 可能出现在请求中,也可能不存在
  • 即使缺失也不应导致 API 出错
  • 通常有默认值或条件逻辑

示例请求体

{
  "username": "sample_user",
  "password": "secret123",
  "description": "Loves backend development"
}

这里:

  • usernamepassword → 必填
  • description → 可选

🧠 类比

请求体就像一张表单:

  • 必填字段 = 必答的问题
  • 可选字段 = 你可以跳过的额外细节

Spring Boot 如何处理缺失字段

Spring Boot(通过 Jackson):

  • 自动将 JSON 映射为 Java 对象
  • 将缺失的字段设为 null
  • 支持默认值和验证注解

无需手动解析。

常见使用场景

  • ✅ 部分数据提交
  • ✅ 向后兼容
  • ✅ 可选的用户偏好
  • ✅ 功能开关
  • ✅ API 演进

代码示例(端到端)

✅ 示例 1:带验证和默认值的可选字段

使用场景

创建一个用户,其中部分字段为可选。

第 1 步 – 请求 DTO

package com.example.demo.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public class CreateUserRequest {

    @NotBlank(message = "Username is required")
    private String username;

    @NotBlank(message = "Password is required")
    @Size(min = 6, message = "Password must be at least 6 characters")
    private String password;

    // Optional field
    private String description;

    // Optional field with default value
    private boolean notificationsEnabled = false;

    // Getters and setters
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isNotificationsEnabled() {
        return notificationsEnabled;
    }

    public void setNotificationsEnabled(boolean notificationsEnabled) {
        this.notificationsEnabled = notificationsEnabled;
    }
}

第 2 步 – REST 控制器

package com.example.demo.controller;

import com.example.demo.dto.CreateUserRequest;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@Valid @RequestBody CreateUserRequest request) {

        String description = request.getDescription() != null
                ? request.getDescription()
                : "No description provided";

        return "User created successfully. " +
               "username=" + request.getUsername() +
               ", description=" + description +
               ", notificationsEnabled=" + request.isNotificationsEnabled();
    }
}

第 3 步 – 使用 cURL 测试

✅ 请求(缺少可选字段)

curl -X POST http://localhost:8080/users \
     -H "Content-Type: application/json" \
     -d '{
           "username": "sample_user",
           "password": "secret123"
         }'

✅ 响应

User created successfully. username=sample_user, description=No description provided, notificationsEnabled=false

❌ 请求(缺少必填字段)

curl -X POST http://localhost:8080/users \
     -H "Content-Type: application/json" \
     -d '{
           "username": "sample_user"
         }'

❌ 响应

{
  "status": 400,
  "error": "Bad Request",
  "message": "Password is required"
}

✅ 示例 2:使用 Optional 的可选字段(最适合 PATCH)

使用场景

部分更新用户偏好设置。

第 1 步 – 请求 DTO

package com.example.demo.dto;

import java.util.Optional;

public class UpdatePreferencesRequest {

    private Optional<String> theme = Optional.empty();
    private Optional<Boolean> notificationsEnabled = Optional.empty();

    public Optional<String> getTheme() {
        return theme;
    }

    public void setTheme(Optional<String> theme) {
        this.theme = theme;
    }

    public Optional<Boolean> getNotificationsEnabled() {
        return notificationsEnabled;
    }

    public void setNotificationsEnabled(Optional<Boolean> notificationsEnabled) {
        this.notificationsEnabled = notificationsEnabled;
    }
}

第 2 步 – 控制器

package com.example.demo.controller;

import com.example.demo.dto.UpdatePreferencesRequest;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserPreferenceController {

第 3 步 – 使用 cURL 测试

✅ 部分更新(仅主题)

curl -X PATCH http://localhost:8080/users/42/preferences \
     -H "Content-Type: application/json" \
     -d '{"theme":"dark"}'

✅ 响应

Preferences updated for user 42. theme=dark, notificationsEnabled=true

✅ 部分更新(仅通知标志)

curl -X PATCH http://localhost:8080/users/42/preferences \
     -H "Content-Type: application/json" \
     -d '{"notificationsEnabled":false}'

✅ 响应

Preferences updated for user 42. theme=light, notificationsEnabled=false

要点

  • 可选字段 让 API 在不破坏现有客户端的情况下演进。
  • Spring Boot(Jackson)会自动将缺失的 JSON 属性映射为 null 或默认值。
  • 对必填字段使用 验证注解@NotBlank@Size 等)。
  • 对于 部分更新PATCH),将字段包装在 Optional 中可以明确意图,避免 null 检查的样板代码。

通过应用这些模式,您将构建既 健壮对开发者友好 的 API。祝编码愉快!

package com.example.demo.dto;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/preferences")
public class PreferencesController {

    @PatchMapping
    public String updatePreferences(@RequestBody UpdatePreferencesRequest request) {

        request.getTheme()
               .ifPresent(t -> System.out.println("Updating theme to: " + t));

        request.getNotificationsEnabled()
               .ifPresent(n -> System.out.println("Updating notifications: " + n));

        return "Preferences updated successfully";
    }
}

第3步:使用 cURL 测试

✅ 请求(仅提供一个字段)

curl -X PATCH http://localhost:8080/preferences \
     -H "Content-Type: application/json" \
     -d '{
           "theme": "dark"
         }'

✅ 响应

Preferences updated successfully

Best Practices

  • 仅验证必填字段 – 避免对可选字段添加验证约束。
  • 提供合理的默认值 – 防止不必要的客户端工作。
  • 主要在部分更新时使用 Optional – 适用于 PATCH,而不是所有 DTO。
  • 设计向后兼容的 API – 可选字段允许安全演进。
  • 显式处理 null – 永不假设可选字段始终存在。

结论

正确处理可选字段是 Spring Boot 中 核心 API 设计技能。通过使用:

  • 验证注解
  • 默认值
  • 在适当情况下使用 Optional

您可以构建 灵活、稳健且对初学者友好 的 API。

掌握 在 Spring Boot 中处理请求体中的可选字段 将巩固您的 Java 编程 基础,并帮助您通过真实的后端模式 学习 Java

行动号召

💬 对可选字段或请求验证有疑问吗?
👇 请在下方评论区留言!

有用资源

Back to Blog

相关文章

阅读更多 »