This is an automated email from the ASF dual-hosted git repository. vy pushed a commit to branch MapMessage-JSON-non-finite-number in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 254393920a287c40d886605e234beb31ca2e1e8a Author: Volkan Yazıcı <[email protected]> AuthorDate: Tue Jun 2 09:13:38 2026 +0200 Fix handling of non-finite numbers while encoding `MapMessage` to JSON --- .../logging/log4j/message/MapMessageTest.java | 26 +++++++++++++++++++ .../log4j/message/MapMessageJsonFormatter.java | 30 +++++++++++++++++----- .../fix-MapMessage-JSON-non-finite-number.xml | 12 +++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/MapMessageTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/MapMessageTest.java index db29a18949..1b45f7b8a0 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/MapMessageTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/MapMessageTest.java @@ -32,6 +32,8 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.util.StringBuilderFormattable; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; /** * @@ -171,6 +173,30 @@ class MapMessageTest { assertEquals(expectedJson, actualJson); } + @ParameterizedTest + @ValueSource(doubles = {Double.NEGATIVE_INFINITY, Double.NaN, Double.POSITIVE_INFINITY}) + void testJsonFormatterDoubleNonFiniteSupport(final double number) { + final String expectedJson = String.format("{'number':'%s','numbers':['%s']}", number, number) + .replace('\'', '"'); + final String actualJson = new ObjectMapMessage() + .with("number", number) + .with("numbers", new double[] {number}) + .getFormattedMessage(new String[] {"JSON"}); + assertEquals(expectedJson, actualJson); + } + + @ParameterizedTest + @ValueSource(floats = {Float.NEGATIVE_INFINITY, Float.NaN, Float.POSITIVE_INFINITY}) + void testJsonFormatterFloatNonFiniteSupport(final float number) { + final String expectedJson = String.format("{'number':'%s','numbers':['%s']}", number, number) + .replace('\'', '"'); + final String actualJson = new ObjectMapMessage() + .with("number", number) + .with("numbers", new float[] {number}) + .getFormattedMessage(new String[] {"JSON"}); + assertEquals(expectedJson, actualJson); + } + @Test void testJsonFormatterInfiniteRecursionPrevention() { final List<Object> recursiveValue = Arrays.asList(1, null); diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.java index c5e5127f53..a309107471 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.java @@ -233,13 +233,13 @@ enum MapMessageJsonFormatter { private static void formatNumber(final StringBuilder sb, final Number number) { if (number instanceof BigDecimal) { final BigDecimal decimalNumber = (BigDecimal) number; - sb.append(decimalNumber.toString()); + sb.append(decimalNumber); } else if (number instanceof Double) { final double doubleNumber = (Double) number; - sb.append(doubleNumber); + formatDouble(sb, doubleNumber); } else if (number instanceof Float) { final float floatNumber = (float) number; - sb.append(floatNumber); + formatFloat(sb, floatNumber); } else if (number instanceof Byte || number instanceof Short || number instanceof Integer @@ -252,11 +252,29 @@ enum MapMessageJsonFormatter { if (Double.compare((double) longNumber, doubleValue) == 0) { sb.append(longNumber); } else { - sb.append(doubleValue); + formatDouble(sb, doubleValue); } } } + private static void formatDouble(StringBuilder sb, double doubleNumber) { + // Follows the same logic as Jackson's JsonWriteFeature#WRITE_NAN_AS_STRINGS feature. + if (!Double.isFinite(doubleNumber)) { + formatString(sb, Double.toString(doubleNumber)); + } else { + sb.append(doubleNumber); + } + } + + private static void formatFloat(StringBuilder sb, float floatNumber) { + // Follows the same logic as Jackson's JsonWriteFeature#WRITE_NAN_AS_STRINGS feature. + if (!Float.isFinite(floatNumber)) { + formatString(sb, Float.toString(floatNumber)); + } else { + sb.append(floatNumber); + } + } + private static void formatBoolean(final StringBuilder sb, final boolean booleanValue) { sb.append(booleanValue); } @@ -352,7 +370,7 @@ enum MapMessageJsonFormatter { sb.append(COMMA); } final float item = items[itemIndex]; - sb.append(item); + formatFloat(sb, item); } sb.append(RBRACE); } @@ -364,7 +382,7 @@ enum MapMessageJsonFormatter { sb.append(COMMA); } final double item = items[itemIndex]; - sb.append(item); + formatDouble(sb, item); } sb.append(RBRACE); } diff --git a/src/changelog/.2.x.x/fix-MapMessage-JSON-non-finite-number.xml b/src/changelog/.2.x.x/fix-MapMessage-JSON-non-finite-number.xml new file mode 100644 index 0000000000..177291e651 --- /dev/null +++ b/src/changelog/.2.x.x/fix-MapMessage-JSON-non-finite-number.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entry xmlns="https://logging.apache.org/xml/ns" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + https://logging.apache.org/xml/ns + https://logging.apache.org/xml/ns/log4j-changelog-0.xsd" + type="fixed"> + <issue id="TBD" link="https://github.com/apache/logging-log4j2/pull/TBD"/> + <description format="asciidoc"> + Fix handling of non-finite numbers while encoding `MapMessage` to JSON + </description> +</entry>
