How do you handle optional fields in request body in Spring Boot?

Published: (December 26, 2025 at 03:48 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Think about filling out a signup form online.
Some fields like username and password are mandatory, while others like profile description or preferences are optional.
You wouldn’t expect the form to fail just because you skipped an optional field—right?

The same idea applies to REST APIs. When a client sends a request body, not every field should be required. Knowing how to handle optional fields in request body in Spring Boot is essential for building flexible, backward‑compatible, and beginner‑friendly APIs.

In this blog, you’ll learn this concept step by step, using simple language, real‑world analogies, and complete end‑to‑end examples with cURL requests and responses.

Core Concepts

What Are Optional Fields in a Request Body?

Optional fields are JSON properties that:

  • May or may not be present in the request
  • Should not break the API if missing
  • Often have default values or conditional logic

Example request body

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

Here:

  • username, password → required
  • description → optional

🧠 Analogy

A request body is like a form:

  • Required fields = mandatory questions
  • Optional fields = extra details you may skip

How Spring Boot Handles Missing Fields

Spring Boot (via Jackson):

  • Maps JSON to Java objects automatically
  • Sets missing fields to null
  • Allows default values and validation annotations

No manual parsing is needed.

Common Use Cases

  • ✅ Partial data submission
  • ✅ Backward compatibility
  • ✅ Optional user preferences
  • ✅ Feature toggles
  • ✅ Evolving APIs

Code Examples (End‑to‑End)

✅ Example 1: Optional Fields with Validation and Default Values

Use Case

Create a user where some fields are optional.

Step 1 – Request 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;
    }
}

Step 2 – REST Controller

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

Step 3 – Test with cURL

✅ Request (Optional Fields Missing)

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

✅ Response

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

❌ Request (Missing Required Field)

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

❌ Response

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

✅ Example 2: Optional Fields Using Optional (Best for PATCH)

Use Case

Update user preferences partially.

Step 1 – Request 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;
    }
}

Step 2 – Controller

package com.example.demo.controller;

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

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

    @PatchMapping("/{id}/preferences")
    public String updatePreferences(@PathVariable Long id,
                                    @RequestBody UpdatePreferencesRequest request) {

        // Simulated existing user data
        String currentTheme = "light";
        boolean currentNotifications = true;

        // Apply updates only if present
        String newTheme = request.getTheme().orElse(currentTheme);
        boolean newNotifications = request.getNotificationsEnabled()
                                          .orElse(currentNotifications);

        // In a real app you would persist the changes here
        return "Preferences updated for user " + id +
               ". theme=" + newTheme +
               ", notificationsEnabled=" + newNotifications;
    }
}

Step 3 – Test with cURL

✅ Partial Update (only theme)

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

✅ Response

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

✅ Partial Update (only notifications flag)

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

✅ Response

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

Takeaways

  • Optional fields let APIs evolve without breaking existing clients.
  • Spring Boot (Jackson) automatically maps missing JSON properties to null or default values.
  • Use validation annotations (@NotBlank, @Size, etc.) for required fields.
  • For partial updates (PATCH), wrapping fields in Optional makes intent explicit and avoids null‑checking boilerplate.

By applying these patterns, you’ll build APIs that are both robust and developer‑friendly. Happy coding!

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

Step 3: Test with cURL

✅ Request (Only One Field Provided)

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

✅ Response

Preferences updated successfully

Best Practices

  • Validate only required fields – avoid marking optional fields with validation constraints.
  • Provide sensible defaults – prevent unnecessary client‑side work.
  • Use Optional mainly for partial updates – ideal for PATCH, not for every DTO.
  • Design APIs for backward compatibility – optional fields allow safe evolution.
  • Handle null values explicitly – never assume optional fields are always present.

Conclusion

Handling optional fields correctly is a core API‑design skill in Spring Boot. By using:

  • Validation annotations
  • Default values
  • Optional where appropriate

you can build APIs that are flexible, robust, and beginner‑friendly.

Mastering handling optional fields in request bodies in Spring Boot will strengthen your Java programming fundamentals and help you learn Java with real‑world backend patterns.

Call to Action

💬 Have questions about optional fields or request validation?
👇 Drop them in the comments below!

Helpful Resources

Back to Blog

Related posts

Read more »