diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 5ba8e773..6a3a9586 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -249,3 +249,9 @@ Arthur Chan (@arthurscchan) * Reported, contributed fix for #618: `ArrayIndexOutOfBoundsException` thrown for invalid ending XML string when using JDK default Stax XML parser (2.17.0) + +Alex H (@ahcodedthat) + +* Contribtued #643: XML serialization of floating-point infinity is incompatible + with JAXB and XML Schema + (2.17.0) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 51513551..72b5951e 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -18,6 +18,9 @@ Project: jackson-dataformat-xml (FromXmlParser.Feature.AUTO_DETECT_XSI_TYPE) #637: `JacksonXmlAnnotationIntrospector.findNamespace()` should properly merge namespace information +#643: XML serialization of floating-point infinity is incompatible + with JAXB and XML Schema + (contributed by Alex H) * Upgrade Woodstox to 6.6.1 (latest at the time) 2.16.2 (09-Mar-2024) diff --git a/src/main/java/com/fasterxml/jackson/dataformat/xml/ser/ToXmlGenerator.java b/src/main/java/com/fasterxml/jackson/dataformat/xml/ser/ToXmlGenerator.java index 73c4e673..7721faeb 100644 --- a/src/main/java/com/fasterxml/jackson/dataformat/xml/ser/ToXmlGenerator.java +++ b/src/main/java/com/fasterxml/jackson/dataformat/xml/ser/ToXmlGenerator.java @@ -106,6 +106,37 @@ public enum Feature implements FormatFeature * @since 2.17 */ AUTO_DETECT_XSI_TYPE(false), + + /** + * Feature that determines how floating-point infinity values are + * serialized. + *
+ * By default, {@link Float#POSITIVE_INFINITY} and + * {@link Double#POSITIVE_INFINITY} are serialized as {@code Infinity}, + * and {@link Float#NEGATIVE_INFINITY} and + * {@link Double#NEGATIVE_INFINITY} are serialized as + * {@code -Infinity}. This is the representation that Java normally + * uses for these values (see {@link Float#toString(float)} and + * {@link Double#toString(double)}), but JAXB and other XML + * Schema-conforming readers won't understand it. + *
+ * With this feature enabled, these values are instead serialized as
+ * {@code INF} and {@code -INF}, respectively. This is the
+ * representation that XML Schema and JAXB use (see the XML Schema
+ * primitive types
+ * float
+ * and
+ * double
).
+ *
+ * When deserializing, Jackson always understands both representations, + * so there is no corresponding + * {@link com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser.Feature}. + *
+ * Feature is disabled by default for backwards compatibility.
+ *
+ * @since 2.17
+ */
+ WRITE_XML_SCHEMA_CONFORMING_FLOATS(false),
;
final boolean _defaultState;
@@ -1174,6 +1205,11 @@ public void writeNumber(long l) throws IOException
@Override
public void writeNumber(double d) throws IOException
{
+ if (Double.isInfinite(d) && isEnabled(Feature.WRITE_XML_SCHEMA_CONFORMING_FLOATS)) {
+ writeNumber(d > 0d ? "INF" : "-INF");
+ return;
+ }
+
_verifyValueWrite("write number");
if (_nextName == null) {
handleMissingName();
@@ -1202,6 +1238,11 @@ public void writeNumber(double d) throws IOException
@Override
public void writeNumber(float f) throws IOException
{
+ if (Float.isInfinite(f) && isEnabled(Feature.WRITE_XML_SCHEMA_CONFORMING_FLOATS)) {
+ writeNumber(f > 0f ? "INF" : "-INF");
+ return;
+ }
+
_verifyValueWrite("write number");
if (_nextName == null) {
handleMissingName();
diff --git a/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/TestSerialization.java b/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/TestSerialization.java
index 0d493201..de4b490c 100644
--- a/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/TestSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/dataformat/xml/ser/TestSerialization.java
@@ -1,9 +1,9 @@
package com.fasterxml.jackson.dataformat.xml.ser;
-import java.io.*;
import java.util.*;
import com.fasterxml.jackson.annotation.JsonProperty;
+
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.XmlTestBase;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
@@ -31,6 +31,22 @@ static class AttrAndElem
public int attr = 42;
}
+ static class Floats
+ {
+ public float elem;
+
+ @JacksonXmlProperty(isAttribute=true, localName="attr")
+ public float attr;
+ }
+
+ static class Doubles
+ {
+ public double elem;
+
+ @JacksonXmlProperty(isAttribute=true, localName="attr")
+ public double attr;
+ }
+
static class WrapperBean