Skip to content

BigDecimal in multi-value request body deserializes differently than single-value #24479

@xdom

Description

@xdom

Affects: spring-webflux:5.2.3.RELEASE


Given a WebFlux RestController has an endpoint mapped, with @RequestBody of type Flux<BigDecimal> and returns the first value of reactive stream as a response,
when calling the endpoint with payload [ -1E+2 ] (array of floats written in E notation),
then response contains -100.0, instead of -1E+2.

(Note: problem lays in deserialization of request body, not serialization of the response)

When request body is mapped as a single-value, i.e. Mono<BigDecimal>, the request body is not normalized and response looks as expected. Non-reactive servlet controller also works consistently, as expected, for both single-value BigDecimal request body and multi-value List<BigDecimal>.

Test to reproduce (single-value testcase passes, multi-values testcase fails):

package com.example.demo;

import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.math.BigDecimal;

class MyTest {
    private final WebTestClient client = WebTestClient.bindToController(new TestController()).build();

    @Test
    void shouldDeserializeSingleBigDecimal() {
        client.post().uri("/single")
              .contentType(MediaType.APPLICATION_JSON)
              .bodyValue("-1E+2")
              .exchange()
              .expectStatus().isOk()
              .expectBody().json("-1E+2");
    }

    @Test
    void shouldDeserializeMultipleBigDecimals() {
        client.post().uri("/multiple")
              .contentType(MediaType.APPLICATION_JSON)
              .bodyValue("[ -1E+2 ]")
              .exchange()
              .expectStatus().isOk()
              .expectBody().json("-1E+2");
    }

    @RestController
    static class TestController {

        @PostMapping("/single")
        Mono<BigDecimal> single(@RequestBody Mono<BigDecimal> entity) {
            return entity;
        }

        @PostMapping("/multiple")
        Mono<BigDecimal> multiple(@RequestBody Flux<BigDecimal> values) {
            return values.single();
        }
    }
}

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions