Why @RequestBody Is More Than Just JSON: Handling Multiple Request Formats in Spring Boot

This article explains how Spring MVC’s @RequestBody annotation is a universal entry point for HTTP request bodies, supporting JSON, XML, plain text, binary streams, maps, lists, and custom media types through its HttpMessageConverter mechanism, with concrete code examples and configuration details.

LuTiao Programming
LuTiao Programming
LuTiao Programming
Why @RequestBody Is More Than Just JSON: Handling Multiple Request Formats in Spring Boot

Why @RequestBody supports many formats

Spring MVC processes the request body through the HttpMessageConverter mechanism. The framework selects a converter based on the request Content‑Type , the target method‑parameter type, and the converters that are registered in the application context.

application/json → MappingJackson2HttpMessageConverter application/xml → MappingJackson2XmlHttpMessageConverter text/plain → StringHttpMessageConverter application/octet-stream → ByteArrayHttpMessageConverter The power of @RequestBody therefore comes from the message‑conversion infrastructure, not from the annotation itself.

Receiving JSON (the most common case)

package com.icoderoad.controller;
import com.icoderoad.dto.UserDTO;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {
    @PostMapping("/create")
    public String create(@RequestBody UserDTO userDTO) {
        return "用户名:" + userDTO.getUsername();
    }
}
package com.icoderoad.dto;
public class UserDTO {
    private String username;
    private Integer age;
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}
POST /user/create
Content-Type: application/json
{
  "username": "icoderoad",
  "age": 18
}

The request is handled by MappingJackson2HttpMessageConverter, which deserialises JSON into UserDTO.

Receiving XML

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>
package com.icoderoad.dto;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "user")
public class XmlUserDTO {
    private String username;
    private Integer age;
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
}
package com.icoderoad.controller;
import com.icoderoad.dto.XmlUserDTO;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/xml")
public class XmlController {
    @PostMapping(value = "/receive", consumes = "application/xml")
    public String receiveXml(@RequestBody XmlUserDTO dto) {
        return dto.getUsername();
    }
}
<user>
    <username>icoderoad</username>
    <age>20</age>
</user>

Receiving plain text (common in webhook callbacks)

package com.icoderoad.controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/text")
public class TextController {
    @PostMapping(value = "/receive", consumes = "text/plain")
    public String receive(@RequestBody String body) {
        System.out.println(body);
        return "success";
    }
}
Content-Type: text/plain
hello spring boot

The underlying converter is StringHttpMessageConverter.

Receiving binary data (byte[])

package com.icoderoad.controller;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/binary")
public class BinaryController {
    @PostMapping(value = "/upload", consumes = "application/octet-stream")
    public String upload(@RequestBody byte[] data) {
        System.out.println("数据长度:" + data.length);
        return "ok";
    }
}

The request is processed by ByteArrayHttpMessageConverter. This is suitable for protobuf, image streams, audio streams, or any custom binary protocol.

Receiving dynamic fields with Map

package com.icoderoad.controller;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

@RestController
@RequestMapping("/map")
public class MapController {
    @PostMapping("/receive")
    public String receive(@RequestBody Map<String, Object> body) {
        System.out.println(body);
        return "ok";
    }
}
{
  "username": "icoderoad",
  "role": "admin",
  "score": 99
}

Receiving a List of objects (batch operations)

package com.icoderoad.controller;
import com.icoderoad.dto.UserDTO;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/batch")
public class BatchController {
    @PostMapping("/save")
    public String save(@RequestBody List<UserDTO> list) {
        return "数据量:" + list.size();
    }
}
[
  {"username": "tom", "age": 18},
  {"username": "jack", "age": 20}
]

Streaming large files with InputStream

Using @RequestBody byte[] loads the entire payload into memory, which can cause OOM for very large files. Reading the raw InputStream from the servlet request avoids this.

package com.icoderoad.controller;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.*;
import java.io.InputStream;

@RestController
@RequestMapping("/stream")
public class StreamController {
    @PostMapping("/upload")
    public String upload(HttpServletRequest request) throws Exception {
        InputStream inputStream = request.getInputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) != -1) {
            System.out.println("读取字节数:" + len);
        }
        return "success";
    }
}

How Spring Boot auto‑detects these formats

Spring Boot’s HttpMessageConvertersAutoConfiguration scans the classpath for libraries such as Jackson, XML support, Gson, or Kotlin Serialization and registers the corresponding converters dynamically. Adding a single dependency like jackson-dataformat-xml instantly enables XML handling.

Custom HttpMessageConverter – advanced use case

When a system requires a proprietary protocol, protobuf, encrypted messages, or a private media type, a custom HttpMessageConverter can be implemented.

package com.icoderoad.converter;
import org.springframework.http.*;
import org.springframework.http.converter.*;
import org.springframework.stereotype.Component;
import java.io.IOException;

@Component
public class CustomMessageConverter extends AbstractHttpMessageConverter<String> {
    public CustomMessageConverter() {
        super(new MediaType("application", "x-icoderoad"));
    }
    @Override
    protected boolean supports(Class<?> clazz) {
        return String.class == clazz;
    }
    @Override
    protected String readInternal(Class<? extends String> clazz, HttpInputMessage inputMessage) throws IOException {
        return new String(inputMessage.getBody().readAllBytes());
    }
    @Override
    protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException {
        outputMessage.getBody().write(s.getBytes());
    }
}

Requests with Content-Type: application/x-icoderoad are automatically handled by CustomMessageConverter.

Typical scenarios where non‑JSON formats appear

Third‑party payment callbacks: XML, text/plain, form‑urlencoded

IoT device communication: application/octet-stream

Log collection platforms: plain text streams

AI / audio‑video systems: audio/video streams, protobuf, binary data

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

jsonSpring BootXMLbinaryRequestBodycustom converterHttpMessageConverter
LuTiao Programming
Written by

LuTiao Programming

LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.