Why @RequestBody Is More Powerful Than You Think: Handling Multiple Formats Beyond JSON

The article explains that @RequestBody in Spring Boot is not just a JSON deserializer but a unified HTTP request‑body entry point that can process JSON, XML, plain text, binary streams, byte arrays, form data, files and custom media types through Spring MVC's HttpMessageConverter system.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Why @RequestBody Is More Powerful Than You Think: Handling Multiple Formats Beyond JSON

What @RequestBody Really Does

In many Spring Boot projects developers assume @RequestBody only accepts JSON, but it is actually Spring MVC's unified entry for any HTTP request body.

As long as the data is in the request body, Spring can read it using the appropriate HttpMessageConverter based on Content‑Type , the target parameter type, and the converters registered on the classpath.

Supported Formats

JSON

XML

Plain text

Binary streams (application/octet-stream)

byte[]

Form‑urlencoded data

File streams

Custom media types

Typical JSON Example

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

Request:

POST /user/create
Content-Type: application/json
{
  "username": "icoderoad",
  "age": 18
}

Handled by MappingJackson2HttpMessageConverter.

XML Support

Add the Jackson XML dependency:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

Define an XML DTO:

package com.icoderoad.dto;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "user")
public class XmlUserDTO {
    private String username;
    private Integer age;
    // getters and setters omitted for brevity
}

Controller:

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

XML request body:

<user>
    <username>icoderoad</username>
    <age>20</age>
</user>

Handled by MappingJackson2XmlHttpMessageConverter.

Plain Text (Webhook) Example

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

Request:

Content-Type: text/plain
hello spring boot

Handled by StringHttpMessageConverter.

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

Handled by ByteArrayHttpMessageConverter.

Dynamic Map Payload

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

Accepts any JSON structure without a fixed DTO.

List of Objects

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

Request body is a JSON array of UserDTO objects.

Streaming Large Files with InputStream

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

Using InputStream avoids loading the whole file into memory, preventing OOM for large uploads.

How Spring Boot Detects Formats

Spring Boot auto‑configures HttpMessageConvertersAutoConfiguration, scans the classpath for libraries such as Jackson, Jackson‑XML, Gson, Kotlin Serialization, etc., and registers the corresponding converters.

Adding a single dependency like jackson-dataformat-xml instantly enables XML support.

Custom Converter Example

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 will be processed by this custom converter.

Typical Scenarios Where Non‑JSON Formats Appear

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

IoT device uploads (application/octet-stream)

Log collection platforms (plain text streams)

AI/audio‑video systems (audio/video streams, protobuf, binary data)

Conclusion

Understanding that @RequestBody is a gateway to Spring MVC's HttpMessageConverter ecosystem reveals that Spring Boot can handle a wide variety of request payloads out of the box. Mastering this layer lets developers move beyond the “only JSON” mindset and build richer, more flexible APIs.

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.

Spring BootSpring MVCContent-Type@RequestBodyHttpMessageConverter
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

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.