Log Message
Solution for _javascript_ compatibility problem with 64-bit integers in JSON (XSTR-541).
Modified Paths
- trunk/xstream/src/java/com/thoughtworks/xstream/io/json/AbstractJsonWriter.java
- trunk/xstream/src/test/com/thoughtworks/xstream/io/json/JsonWriterModeTest.java
- trunk/xstream-distribution/src/content/changes.html
- trunk/xstream-distribution/src/content/faq.html
- trunk/xstream-distribution/src/content/json-tutorial.html
Diff
Modified: trunk/xstream/src/java/com/thoughtworks/xstream/io/json/AbstractJsonWriter.java (2120 => 2121)
--- trunk/xstream/src/java/com/thoughtworks/xstream/io/json/AbstractJsonWriter.java 2013-09-17 22:50:20 UTC (rev 2120)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/io/json/AbstractJsonWriter.java 2013-09-18 21:36:45 UTC (rev 2121)
@@ -111,12 +111,29 @@
* This format can be used to always deserialize into Java again.
* </p>
* <p>
- * This mode cannot be combined with one of the other modes.
+ * This mode cannot combined with {@link #STRICT_MODE} or {@link #DROP_ROOT_MODE}.
* </p>
*
* @since 1.4
*/
public static final int EXPLICIT_MODE = 4;
+ /**
+ * IEEE_754_MODE keeps precision of 64-bit integer values.
+ * <p>
+ * In _javascript_ every number is expressed as 64-bit double value with a precision of 53
+ * bits following IEEE 754. Therefore it is not possible to represent the complete value
+ * range of 64-bit integer values. Any integer value > 2<sup>53</sup>
+ * (9007199254740992) or < -2<sup>53</sup> (-9007199254740992) will therefore be
+ * written as string value.
+ * </p>
+ * <p>
+ * CAUTION: A client must be aware that the element may contain a number or a string value.
+ * </p>
+ *
+ * @since upcoming
+ * @see <a href="" Specification: The Number Type</a>
+ */
+ public static final int IEEE_754_MODE = 8;
public static class Type {
public static Type NULL = new Type();
@@ -408,7 +425,18 @@
endObject();
}
} else {
- addValue(valueToAdd, getType(currentType));
+ if (((mode & IEEE_754_MODE) != 0)
+ && (currentType == long.class || currentType == Long.class)) {
+ long longValue = Long.parseLong(valueToAdd);
+ // _javascript_ supports a maximum of 2^53
+ if (longValue > 9007199254740992L || longValue < -9007199254740992L) {
+ addValue(valueToAdd, Type.STRING);
+ } else {
+ addValue(valueToAdd, getType(currentType));
+ }
+ } else {
+ addValue(valueToAdd, getType(currentType));
+ }
}
return requiredState;
case STATE_END_ELEMENTS:
Modified: trunk/xstream/src/test/com/thoughtworks/xstream/io/json/JsonWriterModeTest.java (2120 => 2121)
--- trunk/xstream/src/test/com/thoughtworks/xstream/io/json/JsonWriterModeTest.java 2013-09-17 22:50:20 UTC (rev 2120)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/io/json/JsonWriterModeTest.java 2013-09-18 21:36:45 UTC (rev 2121)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2011 XStream Committers.
+ * Copyright (C) 2009, 2011, 2013 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
@@ -59,6 +59,8 @@
.asList(new Object[]{
new Object[][]{new Object[0]},
null,
+ new Integer(42),
+ new Long(Long.MAX_VALUE),
new Y(),
x.innerObj,
new ArrayList(),
@@ -173,9 +175,15 @@
suite.addTest(new JsonWriterModeTest(
"optimizedPretty", XStream.NO_REFERENCES, 0, prettyFormat));
suite.addTest(new JsonWriterModeTest(
+ "optimizedCompactIEEE754", XStream.NO_REFERENCES, AbstractJsonWriter.IEEE_754_MODE,
+ compactFormat));
+ suite.addTest(new JsonWriterModeTest(
"explicitCompact", XStream.NO_REFERENCES, AbstractJsonWriter.EXPLICIT_MODE,
compactFormat));
suite.addTest(new JsonWriterModeTest(
+ "explicitCompactIEEE754", XStream.NO_REFERENCES, AbstractJsonWriter.EXPLICIT_MODE
+ | AbstractJsonWriter.IEEE_754_MODE, compactFormat));
+ suite.addTest(new JsonWriterModeTest(
"explicitPretty", XStream.NO_REFERENCES, AbstractJsonWriter.EXPLICIT_MODE,
prettyFormat));
suite.addTest(new JsonWriterModeTest(
Modified: trunk/xstream-distribution/src/content/changes.html (2120 => 2121)
--- trunk/xstream-distribution/src/content/changes.html 2013-09-17 22:50:20 UTC (rev 2120)
+++ trunk/xstream-distribution/src/content/changes.html 2013-09-18 21:36:45 UTC (rev 2121)
@@ -65,6 +65,7 @@
<ul>
<li>Fix missing manifest information.</li>
<li>JIRA:XSTR-729: Add OSGi information to manifests.</li>
+ <li>JIRA:XSTR-541: _javascript_ compatibility problem with 64-bit integers in JSON.</li>
<li>JIRA:XSTR-719: Support replacement of default converter in any case.</li>
<li>JIRA:XSTR-725: processAnnotation performance improvement in concurrent situation.</li>
<li>JIRA:XSTR-721: EnumConverter is more lenient while parsing constants.</li>
Modified: trunk/xstream-distribution/src/content/faq.html (2120 => 2121)
--- trunk/xstream-distribution/src/content/faq.html 2013-09-17 22:50:20 UTC (rev 2120)
+++ trunk/xstream-distribution/src/content/faq.html 2013-09-18 21:36:45 UTC (rev 2121)
@@ -513,8 +513,8 @@
<h2 id="JSON_Jettison_version">Which versions of Jettison are supported?</h2>
- <p>Users of Java 5 or higher can use Jettison 1.2 or higher, users of Java 1.4.2 have to use Jettison 1.0.1. Java
- 1.3 and Jettison 1.1 is not supported.</p>
+ <p>Users of Java 5 or higher can use Jettison 1.2, users of Java 1.4.2 have to use Jettison 1.0.1. Jettison 1.1
+ nor Jettison 1.3 or higher is supported.</p>
<h2 id="JSON_deserialize_top_level_array">Why is it not possible to deserialize a JSON string starting with an array?</h2>
@@ -550,6 +550,18 @@
possibility to express such a construct. You should therefore always set the NO_REFERENCES mode of XStream.
Additionally you cannot use implicit collections, since the properties in a JSON object must have unique names.</p>
+ <h2 id="JSON_JavaScript_Long">Why are my Long values incorrect in _javascript_?</h2>
+
+ <p>_javascript_ does not know about integer values. All numbers are represented with double precition floats using
+ 64 bits (IEEE 754). These types cannot represent technically the complete value range of 64-bit integers like
+ Java's Long. With the JsonWriter you have the possibility since XStream 1.4.5 to set
+ <a href="" to force
+ any long value that is not representable as _javascript_ number to be written as string value in JSON. With the
+ Jettison-based JettisonMappedXmlDriver you may either set a different TypeConverter or force the default converter
+ to write integer values out of the range of 32-bit always as string setting the system property
+ <strong>jettison.mapped.typeconverter.enforce_32bit_integer</strong> to <strong>true</strong> (not available for
+ Jettison 1.0.1 and Java 1.4).</p>
+
<h2 id="JSON_encoding">Why are there invalid characters in my JSON representation?</h2>
<p>The JSON spec requires any JSON string to be in UTF-8 encoding. However, XStream ensures this only if you
Modified: trunk/xstream-distribution/src/content/json-tutorial.html (2120 => 2121)
--- trunk/xstream-distribution/src/content/json-tutorial.html 2013-09-17 22:50:20 UTC (rev 2120)
+++ trunk/xstream-distribution/src/content/json-tutorial.html 2013-09-18 21:36:45 UTC (rev 2121)
@@ -1,6 +1,6 @@
<html>
<!--
- Copyright (C) 2007, 2008, 2010, 2012 XStream committers.
+ Copyright (C) 2007, 2008, 2010, 2012, 2013 XStream committers.
All rights reserved.
The software in this package is published under the terms of the BSD
@@ -32,7 +32,10 @@
(attributes), no properties with same names (as generated for implicit collections), etc. Therefore do not expect
wonders. XStream (and Jettison) try their best, but the procedure to convert any kind of object into JSON is a lossy
transformation and especially deserialization will not be possible for any construct. See also
-<a href=""
+<a href="" for JSON limitations</a>. Also note that any number value in _javascript_ is a
+64-bit double precision float value according IEEE 754 standard. In consequence it is not possible to represent all
+values of a Java long type without loss of precision. See again <a href="" for JSON
+and _javascript_</a>.</p>
<p>Since JSON has no possibility to express references, you should always set the NO_REFERENCES mode writing JSON.</p>
To unsubscribe from this list please visit:
