diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java
index c81f15ff5..0ad6ce477 100644
--- a/src/main/java/org/json/XML.java
+++ b/src/main/java/org/json/XML.java
@@ -26,10 +26,12 @@ of this software and associated documentation files (the "Software"), to deal
import java.io.Reader;
import java.io.StringReader;
+import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Iterator;
+
/**
* This provides static methods to convert an XML text into a JSONObject, and to
* covert a JSONObject into an XML text.
@@ -72,6 +74,8 @@ public class XML {
*/
public static final String NULL_ATTR = "xsi:nil";
+ public static final String TYPE_ATTR = "xsi:type";
+
/**
* Creates an iterator for navigating Code Points in a string instead of
* characters. Once Java7 support is dropped, this can be replaced with
@@ -257,6 +261,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
String string;
String tagName;
Object token;
+ String typeCastClass;
// Test for and skip past these forms:
//
@@ -336,6 +341,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
token = null;
jsonObject = new JSONObject();
boolean nilAttributeFound = false;
+ typeCastClass = null;
for (;;) {
if (token == null) {
token = x.nextToken();
@@ -354,6 +360,9 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
&& NULL_ATTR.equals(string)
&& Boolean.parseBoolean((String) token)) {
nilAttributeFound = true;
+ } else if(config.useValueTypeCast
+ && TYPE_ATTR.equals(string)) {
+ typeCastClass = (String) token;
} else if (!nilAttributeFound) {
jsonObject.accumulate(string,
config.isKeepStrings()
@@ -392,8 +401,13 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
} else if (token instanceof String) {
string = (String) token;
if (string.length() > 0) {
- jsonObject.accumulate(config.getcDataTagName(),
- config.isKeepStrings() ? string : stringToValue(string));
+ if(typeCastClass != null) {
+ jsonObject.accumulate(config.getcDataTagName(),
+ stringToValue(string, typeCastClass));
+ } else {
+ jsonObject.accumulate(config.getcDataTagName(),
+ config.isKeepStrings() ? string : stringToValue(string));
+ }
}
} else if (token == LT) {
@@ -418,6 +432,24 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
}
}
+ /**
+ * This method tries to convert the given string value to the target object
+ * @param string String to convert
+ * @param className target class name
+ * @return JSON value of this string or the string
+ */
+ public static Object stringToValue(String string, String className) {
+ try {
+ if(className.equals(String.class.getName())) return string;
+ Class> clazz = Class.forName(className);
+ Method method = clazz.getMethod("valueOf", String.class);
+ return method.invoke(null, string);
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return stringToValue(string);
+ }
+
/**
* This method is the same as {@link JSONObject#stringToValue(String)}.
*
diff --git a/src/main/java/org/json/XMLParserConfiguration.java b/src/main/java/org/json/XMLParserConfiguration.java
index cf5e10caa..c57c8db36 100644
--- a/src/main/java/org/json/XMLParserConfiguration.java
+++ b/src/main/java/org/json/XMLParserConfiguration.java
@@ -56,6 +56,12 @@ public class XMLParserConfiguration {
*/
private boolean convertNilAttributeToNull;
+ /**
+ * When parsing the XML into JSON, specifies if values with attribute xsi:type="java.lang.Integer"
+ * should be kept as attribute(false), or they should be converted to the given type
+ */
+ public boolean useValueTypeCast;
+
/**
* Default parser configuration. Does not keep strings (tries to implicitly convert
* values), and the CDATA Tag Name is "content".
@@ -106,9 +112,7 @@ public XMLParserConfiguration (final String cDataTagName) {
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
- this.keepStrings = keepStrings;
- this.cDataTagName = cDataTagName;
- this.convertNilAttributeToNull = false;
+ this(keepStrings, cDataTagName, false);
}
/**
@@ -125,9 +129,27 @@ public XMLParserConfiguration (final boolean keepStrings, final String cDataTagN
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
+ this(keepStrings, cDataTagName, convertNilAttributeToNull, false);
+ }
+
+ /**
+ * Configure the parser to use custom settings.
+ * @param keepStrings true
to parse all values as string.
+ * false
to try and convert XML string values into a JSON value.
+ * @param cDataTagName null
to disable CDATA processing. Any other value
+ * to use that value as the JSONObject key name to process as CDATA.
+ * @param convertNilAttributeToNull true
to parse values with attribute xsi:nil="true" as null.
+ * false
to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
+ * @param useValueTypeCast true
to parse values with attribute xsi:type="java.lang.Integer" as
+ * integer, xsi:type="java.lang.String" as string
+ * false
to parse values with attribute xsi:type="java.lang.Integer" as {"xsi:type":"java.lang.Integer"}.
+ */
+ public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
+ final boolean convertNilAttributeToNull, final boolean useValueTypeCast ) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
+ this.useValueTypeCast = useValueTypeCast;
}
/**
diff --git a/src/test/java/org/json/junit/XMLTest.java b/src/test/java/org/json/junit/XMLTest.java
index cf78350b4..2b6f065d5 100644
--- a/src/test/java/org/json/junit/XMLTest.java
+++ b/src/test/java/org/json/junit/XMLTest.java
@@ -972,5 +972,32 @@ public void testIssue537CaseSensitiveHexUnEscapeDirect(){
assertEquals("Case insensitive Entity unescape", expectedStr, actualStr);
}
-
-}
\ No newline at end of file
+
+ /**
+ * test passes when xsi:type="java.lang.String" not converting to string
+ */
+ @Test
+ public void testToJsonWithTypeWhenTypeConversionDisabled() {
+ final String originalXml = "1234";
+ final String expectedJsonString = "{\"root\":{\"id\":{\"xsi:type\":\"java.lang.String\",\"content\":1234}}}";
+ final JSONObject expectedJson = new JSONObject(expectedJsonString);
+ final JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration());
+
+ Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
+ }
+
+ /**
+ * test passes when xsi:type="java.lang.String" converting to String
+ */
+ @Test
+ public void testToJsonWithTypeWhenTypeConversionEnabled() {
+ final String originalXml = "1234"
+ + "1234";
+ final String expectedJsonString = "{\"root\":{\"id2\":1234,\"id1\":\"1234\"}}";
+ final JSONObject expectedJson = new JSONObject(expectedJsonString);
+ final JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration(false,
+ "content", false, true));
+ Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
+ }
+
+}