@@ -26,10 +26,12 @@ of this software and associated documentation files (the "Software"), to deal
2626
2727import java .io .Reader ;
2828import java .io .StringReader ;
29+ import java .lang .reflect .Method ;
2930import java .math .BigDecimal ;
3031import java .math .BigInteger ;
3132import java .util .Iterator ;
3233
34+
3335/**
3436 * This provides static methods to convert an XML text into a JSONObject, and to
3537 * covert a JSONObject into an XML text.
@@ -72,6 +74,8 @@ public class XML {
7274 */
7375 public static final String NULL_ATTR = "xsi:nil" ;
7476
77+ public static final String TYPE_ATTR = "xsi:type" ;
78+
7579 /**
7680 * Creates an iterator for navigating Code Points in a string instead of
7781 * 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
257261 String string ;
258262 String tagName ;
259263 Object token ;
264+ String typeCastClass ;
260265
261266 // Test for and skip past these forms:
262267 // <!-- ... -->
@@ -336,6 +341,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
336341 token = null ;
337342 jsonObject = new JSONObject ();
338343 boolean nilAttributeFound = false ;
344+ typeCastClass = null ;
339345 for (;;) {
340346 if (token == null ) {
341347 token = x .nextToken ();
@@ -354,6 +360,9 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
354360 && NULL_ATTR .equals (string )
355361 && Boolean .parseBoolean ((String ) token )) {
356362 nilAttributeFound = true ;
363+ } else if (config .useValueTypeCast
364+ && TYPE_ATTR .equals (string )) {
365+ typeCastClass = (String ) token ;
357366 } else if (!nilAttributeFound ) {
358367 jsonObject .accumulate (string ,
359368 config .isKeepStrings ()
@@ -392,8 +401,13 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
392401 } else if (token instanceof String ) {
393402 string = (String ) token ;
394403 if (string .length () > 0 ) {
395- jsonObject .accumulate (config .getcDataTagName (),
396- config .isKeepStrings () ? string : stringToValue (string ));
404+ if (typeCastClass != null ) {
405+ jsonObject .accumulate (config .getcDataTagName (),
406+ stringToValue (string , typeCastClass ));
407+ } else {
408+ jsonObject .accumulate (config .getcDataTagName (),
409+ config .isKeepStrings () ? string : stringToValue (string ));
410+ }
397411 }
398412
399413 } else if (token == LT ) {
@@ -418,6 +432,24 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
418432 }
419433 }
420434
435+ /**
436+ * This method tries to convert the given string value to the target object
437+ * @param string String to convert
438+ * @param className target class name
439+ * @return JSON value of this string or the string
440+ */
441+ public static Object stringToValue (String string , String className ) {
442+ try {
443+ if (className .equals (String .class .getName ())) return string ;
444+ Class <?> clazz = Class .forName (className );
445+ Method method = clazz .getMethod ("valueOf" , String .class );
446+ return method .invoke (null , string );
447+ } catch (Exception e ){
448+ e .printStackTrace ();
449+ }
450+ return stringToValue (string );
451+ }
452+
421453 /**
422454 * This method is the same as {@link JSONObject#stringToValue(String)}.
423455 *
0 commit comments