20
20
import com .fasterxml .jackson .core .json .JsonWriteContext ;
21
21
import com .fasterxml .jackson .core .util .JacksonFeatureSet ;
22
22
import com .fasterxml .jackson .dataformat .xml .XmlPrettyPrinter ;
23
+ import com .fasterxml .jackson .dataformat .xml .deser .FromXmlParser ;
23
24
import com .fasterxml .jackson .dataformat .xml .util .DefaultXmlPrettyPrinter ;
24
25
import com .fasterxml .jackson .dataformat .xml .util .StaxUtil ;
25
26
@@ -106,6 +107,34 @@ public enum Feature implements FormatFeature
106
107
* @since 2.17
107
108
*/
108
109
AUTO_DETECT_XSI_TYPE (false ),
110
+
111
+ /**
112
+ * Feature that determines how floating-point infinity values are
113
+ * serialized.
114
+ *<p>
115
+ * By default, {@link Float#POSITIVE_INFINITY} and
116
+ * {@link Double#POSITIVE_INFINITY} are serialized as {@code Infinity},
117
+ * and {@link Float#NEGATIVE_INFINITY} and
118
+ * {@link Double#NEGATIVE_INFINITY} are serialized as
119
+ * {@code -Infinity}. This is the representation that Java normally
120
+ * uses for these values (see {@link Float#toString(float)} and
121
+ * {@link Double#toString(double)}), but JAXB and other XML
122
+ * Schema-conforming readers won't understand it.
123
+ *<p>
124
+ * With this feature enabled, these values are instead serialized as
125
+ * {@code INF} and {@code -INF}, respectively. This is the
126
+ * representation that XML Schema and JAXB use (see the XML Schema
127
+ * primitive types
128
+ * <a href="https://www.w3.org/TR/xmlschema-2/#float"><code>float</code></a>
129
+ * and
130
+ * <a href="https://www.w3.org/TR/xmlschema-2/#double"><code>double</code></a>).
131
+ *<p>
132
+ * When deserializing, Jackson always understands both representations,
133
+ * so there is no corresponding {@link FromXmlParser.Feature}.
134
+ *<p>
135
+ * Feature is disabled by default for backwards compatibility.
136
+ */
137
+ XML_SCHEMA_CONFORMING_FLOATS (false ),
109
138
;
110
139
111
140
final boolean _defaultState ;
@@ -145,7 +174,7 @@ private Feature(boolean defaultState) {
145
174
protected final XMLStreamWriter2 _xmlWriter ;
146
175
147
176
protected final XMLStreamWriter _originalXmlWriter ;
148
-
177
+
149
178
/**
150
179
* Marker flag set if the underlying stream writer has to emulate
151
180
* Stax2 API: this is problematic if trying to use {@link #writeRaw} calls.
@@ -184,7 +213,7 @@ private Feature(boolean defaultState) {
184
213
185
214
/**
186
215
* Marker set when {@link #initGenerator()} has been called or not.
187
- *
216
+ *
188
217
* @since 2.2
189
218
*/
190
219
protected boolean _initialized ;
@@ -218,7 +247,7 @@ private Feature(boolean defaultState) {
218
247
219
248
/**
220
249
* To support proper serialization of arrays it is necessary to keep
221
- * stack of element names, so that we can "revert" to earlier
250
+ * stack of element names, so that we can "revert" to earlier
222
251
*/
223
252
protected LinkedList <QName > _elementNameStack = new LinkedList <QName >();
224
253
@@ -403,7 +432,7 @@ public boolean inRoot() {
403
432
public XMLStreamWriter getStaxWriter () {
404
433
return _xmlWriter ;
405
434
}
406
-
435
+
407
436
/*
408
437
/**********************************************************
409
438
/* Extended API, passing XML specific settings
@@ -424,7 +453,7 @@ public void setNextIsCData(boolean isCData)
424
453
{
425
454
_nextIsCData = isCData ;
426
455
}
427
-
456
+
428
457
public final void setNextName (QName name )
429
458
{
430
459
_nextName = name ;
@@ -433,7 +462,7 @@ public final void setNextName(QName name)
433
462
/**
434
463
* Method that does same as {@link #setNextName}, unless
435
464
* a name has already been set.
436
- *
465
+ *
437
466
* @since 2.1.2
438
467
*/
439
468
public final boolean setNextNameIfMissing (QName name )
@@ -444,11 +473,11 @@ public final boolean setNextNameIfMissing(QName name)
444
473
}
445
474
return false ;
446
475
}
447
-
476
+
448
477
/**
449
478
* Methdod called when a structured (collection, array, map) is being
450
479
* output.
451
- *
480
+ *
452
481
* @param wrapperName Element used as wrapper around elements, if any (null if none)
453
482
* @param wrappedName Element used around individual content items (can not
454
483
* be null)
@@ -491,7 +520,7 @@ public void finishWrappedValue(QName wrapperName, QName wrappedName) throws IOEx
491
520
492
521
/**
493
522
* Trivial helper method called when to add a replicated wrapper name
494
- *
523
+ *
495
524
* @since 2.2
496
525
*/
497
526
public void writeRepeatedFieldName () throws IOException
@@ -500,7 +529,7 @@ public void writeRepeatedFieldName() throws IOException
500
529
_reportError ("Can not write a field name, expecting a value" );
501
530
}
502
531
}
503
-
532
+
504
533
/*
505
534
/**********************************************************
506
535
/* JsonGenerator method overrides
@@ -582,7 +611,7 @@ public final void writeStartArray() throws IOException
582
611
// nothing to do here; no-operation
583
612
}
584
613
}
585
-
614
+
586
615
@ Override
587
616
public final void writeEndArray () throws IOException
588
617
{
@@ -640,7 +669,7 @@ public final void _handleStartObject() throws IOException
640
669
StaxUtil .throwAsGenerationException (e , this );
641
670
}
642
671
}
643
-
672
+
644
673
// note: public just because pretty printer needs to make a callback
645
674
public final void _handleEndObject () throws IOException
646
675
{
@@ -664,7 +693,7 @@ public final void _handleEndObject() throws IOException
664
693
StaxUtil .throwAsGenerationException (e , this );
665
694
}
666
695
}
667
-
696
+
668
697
/*
669
698
/**********************************************************
670
699
/* Output method implementations, textual
@@ -706,12 +735,12 @@ public void writeString(String text) throws IOException
706
735
_xmlWriter .writeCharacters (text );
707
736
}
708
737
_xmlWriter .writeEndElement ();
709
- }
738
+ }
710
739
} catch (XMLStreamException e ) {
711
740
StaxUtil .throwAsGenerationException (e , this );
712
741
}
713
- }
714
-
742
+ }
743
+
715
744
@ Override
716
745
public void writeString (char [] text , int offset , int len ) throws IOException
717
746
{
@@ -751,7 +780,7 @@ public void writeString(char[] text, int offset, int len) throws IOException
751
780
public void writeString (SerializableString text ) throws IOException {
752
781
writeString (text .getValue ());
753
782
}
754
-
783
+
755
784
@ Override
756
785
public void writeRawUTF8String (byte [] text , int offset , int length ) throws IOException
757
786
{
@@ -901,7 +930,7 @@ public void writeRaw(char c) throws IOException
901
930
{
902
931
writeRaw (String .valueOf (c ));
903
932
}
904
-
933
+
905
934
/*
906
935
/**********************************************************
907
936
/* Output method implementations, base64-encoded binary
@@ -987,7 +1016,7 @@ public int writeBinary(Base64Variant b64variant, InputStream data, int dataLengt
987
1016
}
988
1017
989
1018
private void writeStreamAsBinary (org .codehaus .stax2 .typed .Base64Variant stax2base64v ,
990
- InputStream data , int len ) throws IOException , XMLStreamException
1019
+ InputStream data , int len ) throws IOException , XMLStreamException
991
1020
{
992
1021
// base64 encodes up to 3 bytes into a 4 bytes string
993
1022
byte [] tmp = new byte [3 ];
@@ -1024,7 +1053,7 @@ private byte[] toFullBuffer(byte[] data, int offset, int len)
1024
1053
return result ;
1025
1054
}
1026
1055
1027
- private byte [] toFullBuffer (InputStream data , final int len ) throws IOException
1056
+ private byte [] toFullBuffer (InputStream data , final int len ) throws IOException
1028
1057
{
1029
1058
byte [] result = new byte [len ];
1030
1059
int offset = 0 ;
@@ -1174,6 +1203,11 @@ public void writeNumber(long l) throws IOException
1174
1203
@ Override
1175
1204
public void writeNumber (double d ) throws IOException
1176
1205
{
1206
+ if (Double .isInfinite (d ) && isEnabled (Feature .XML_SCHEMA_CONFORMING_FLOATS )) {
1207
+ writeNumber (d > 0d ? "INF" : "-INF" );
1208
+ return ;
1209
+ }
1210
+
1177
1211
_verifyValueWrite ("write number" );
1178
1212
if (_nextName == null ) {
1179
1213
handleMissingName ();
@@ -1202,6 +1236,11 @@ public void writeNumber(double d) throws IOException
1202
1236
@ Override
1203
1237
public void writeNumber (float f ) throws IOException
1204
1238
{
1239
+ if (Float .isInfinite (f ) && isEnabled (Feature .XML_SCHEMA_CONFORMING_FLOATS )) {
1240
+ writeNumber (f > 0f ? "INF" : "-INF" );
1241
+ return ;
1242
+ }
1243
+
1205
1244
_verifyValueWrite ("write number" );
1206
1245
if (_nextName == null ) {
1207
1246
handleMissingName ();
@@ -1418,7 +1457,7 @@ protected boolean checkNextIsUnwrapped()
1418
1457
}
1419
1458
return false ;
1420
1459
}
1421
-
1460
+
1422
1461
protected void handleMissingName () {
1423
1462
throw new IllegalStateException ("No element/attribute name specified when trying to output element" );
1424
1463
}
0 commit comments