From 265b0d5b4a272d05d009a29c0504a6641bdad6ef Mon Sep 17 00:00:00 2001 From: chuuminggg Date: Fri, 16 Oct 2026 14:19:14 +0900 Subject: [PATCH] Preserve JSON numbers when pretty printing and extracting subsections Previously, floating-point numbers in JSON content were read as doubles so pretty printing and beneathPath changed how they were documented. For example, 10.50 became 10.5 and values that cannot be represented exactly as a double lost precision. Such numbers are now read as BigDecimal so that their original value is retained. Signed-off-by: chuuminggg --- .../preprocess/PrettyPrintingContentModifier.java | 2 ++ .../payload/FieldPathPayloadSubsectionExtractor.java | 5 ++++- .../preprocess/PrettyPrintingContentModifierTests.java | 8 ++++++++ .../FieldPathPayloadSubsectionExtractorTests.java | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java index 72c87cb5b..77b243480 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifier.java @@ -29,6 +29,7 @@ import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; +import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.json.JsonMapper; @@ -139,6 +140,7 @@ private static final class JsonPrettyPrinter implements PrettyPrinter { private final ObjectMapper objectMapper = JsonMapper.builder() .enable(SerializationFeature.INDENT_OUTPUT) + .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) .build(); @Override diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java index d6a2d169e..d4a2aa456 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractor.java @@ -13,6 +13,7 @@ import org.jspecify.annotations.Nullable; import tools.jackson.core.JacksonException; +import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.json.JsonMapper; @@ -31,7 +32,9 @@ public class FieldPathPayloadSubsectionExtractor implements PayloadSubsectionExtractor { - private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper objectMapper = JsonMapper.builder() + .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) + .build(); private static final ObjectMapper prettyPrintingOjectMapper = JsonMapper.builder() .enable(SerializationFeature.INDENT_OUTPUT) diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java index 28dbab1ac..29c11362c 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/operation/preprocess/PrettyPrintingContentModifierTests.java @@ -31,6 +31,14 @@ void prettyPrintJson() { .isEqualTo(String.format("{%n \"a\" : 5%n}").getBytes()); } + @Test + void prettyPrintJsonPreservesNumbers() { + String content = "{\"a\":10.50,\"b\":0.1000000000000000055511151231257827,\"c\":12345678901234567890.123}"; + assertThat(new String(new PrettyPrintingContentModifier().modifyContent(content.getBytes(), null))) + .isEqualTo(String.format("{%n \"a\" : 10.50,%n \"b\" : 0.1000000000000000055511151231257827,%n" + + " \"c\" : 12345678901234567890.123%n}")); + } + @Test void prettyPrintXml() { assertThat(new PrettyPrintingContentModifier() diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java index 6bd2a83b8..91565d20c 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/FieldPathPayloadSubsectionExtractorTests.java @@ -148,6 +148,16 @@ void extractedSubsectionIsNotPrettyPrintedWhenInputIsNotPrettyPrinted() throws J assertThat(new String(extractedSubsection)).isEqualTo(new String(subsection)); } + @Test + void extractedSubsectionPreservesNumbers() { + byte[] extractedSubsection = new FieldPathPayloadSubsectionExtractor("a").extractSubsection( + "{\"a\":{\"b\":10.50,\"c\":0.1000000000000000055511151231257827,\"d\":12345678901234567890.123}}" + .getBytes(), + MediaType.APPLICATION_JSON); + assertThat(new String(extractedSubsection)) + .isEqualTo("{\"b\":10.50,\"c\":0.1000000000000000055511151231257827,\"d\":12345678901234567890.123}"); + } + @Test void extractNonExistentSubsection() { assertThatThrownBy(() -> new FieldPathPayloadSubsectionExtractor("a.c")