diff --git a/src/main/java/org/json/JSONML.java b/src/main/java/org/json/JSONML.java
index bde97a680..6ec997061 100644
--- a/src/main/java/org/json/JSONML.java
+++ b/src/main/java/org/json/JSONML.java
@@ -22,6 +22,33 @@ public class JSONML {
public JSONML() {
}
+ /**
+ * Safely cast parse result to JSONArray with proper type checking.
+ * @param result The result from parse() method
+ * @return JSONArray if result is a JSONArray
+ * @throws JSONException if result is not a JSONArray
+ */
+ private static JSONArray toJSONArraySafe(Object result) throws JSONException {
+ if (result instanceof JSONArray) {
+ return (JSONArray) result;
+ }
+ throw new JSONException("Expected JSONArray but got " +
+ (result == null ? "null" : result.getClass().getSimpleName()));
+ }
+
+ /**
+ * Safely cast parse result to JSONObject with proper type checking.
+ * @param result The result from parse() method
+ * @return JSONObject if result is a JSONObject
+ * @throws JSONException if result is not a JSONObject
+ */
+ private static JSONObject toJSONObjectSafe(Object result) throws JSONException {
+ if (result instanceof JSONObject) {
+ return (JSONObject) result;
+ }
+ throw new JSONException("Expected JSONObject but got " +
+ (result == null ? "null" : result.getClass().getSimpleName()));
+ }
/**
* Parse XML values and store them in a JSONArray.
@@ -276,7 +303,7 @@ private static Object parse(
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string) throws JSONException {
- return (JSONArray)parse(new XMLTokener(string), true, null, JSONMLParserConfiguration.ORIGINAL, 0);
+ return toJSONArraySafe(parse(new XMLTokener(string), true, null, JSONMLParserConfiguration.ORIGINAL, 0));
}
@@ -298,7 +325,7 @@ public static JSONArray toJSONArray(String string) throws JSONException {
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
- return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings, 0);
+ return toJSONArraySafe(parse(new XMLTokener(string), true, null, keepStrings, 0));
}
@@ -323,7 +350,7 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string, JSONMLParserConfiguration config) throws JSONException {
- return (JSONArray)parse(new XMLTokener(string), true, null, config, 0);
+ return toJSONArraySafe(parse(new XMLTokener(string), true, null, config, 0));
}
@@ -347,7 +374,7 @@ public static JSONArray toJSONArray(String string, JSONMLParserConfiguration con
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x, JSONMLParserConfiguration config) throws JSONException {
- return (JSONArray)parse(x, true, null, config, 0);
+ return toJSONArraySafe(parse(x, true, null, config, 0));
}
@@ -369,7 +396,7 @@ public static JSONArray toJSONArray(XMLTokener x, JSONMLParserConfiguration conf
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
- return (JSONArray)parse(x, true, null, keepStrings, 0);
+ return toJSONArraySafe(parse(x, true, null, keepStrings, 0));
}
@@ -386,7 +413,7 @@ public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JS
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
- return (JSONArray)parse(x, true, null, false, 0);
+ return toJSONArraySafe(parse(x, true, null, false, 0));
}
@@ -404,7 +431,7 @@ public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string) throws JSONException {
- return (JSONObject)parse(new XMLTokener(string), false, null, false, 0);
+ return toJSONObjectSafe(parse(new XMLTokener(string), false, null, false, 0));
}
@@ -424,7 +451,7 @@ public static JSONObject toJSONObject(String string) throws JSONException {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
- return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings, 0);
+ return toJSONObjectSafe(parse(new XMLTokener(string), false, null, keepStrings, 0));
}
@@ -446,7 +473,7 @@ public static JSONObject toJSONObject(String string, boolean keepStrings) throws
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string, JSONMLParserConfiguration config) throws JSONException {
- return (JSONObject)parse(new XMLTokener(string), false, null, config, 0);
+ return toJSONObjectSafe(parse(new XMLTokener(string), false, null, config, 0));
}
@@ -464,7 +491,7 @@ public static JSONObject toJSONObject(String string, JSONMLParserConfiguration c
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
- return (JSONObject)parse(x, false, null, false, 0);
+ return toJSONObjectSafe(parse(x, false, null, false, 0));
}
@@ -484,7 +511,7 @@ public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
- return (JSONObject)parse(x, false, null, keepStrings, 0);
+ return toJSONObjectSafe(parse(x, false, null, keepStrings, 0));
}
@@ -506,7 +533,7 @@ public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x, JSONMLParserConfiguration config) throws JSONException {
- return (JSONObject)parse(x, false, null, config, 0);
+ return toJSONObjectSafe(parse(x, false, null, config, 0));
}
diff --git a/src/test/java/org/json/junit/JSONMLTest.java b/src/test/java/org/json/junit/JSONMLTest.java
index 5a360dd59..93a6821d8 100644
--- a/src/test/java/org/json/junit/JSONMLTest.java
+++ b/src/test/java/org/json/junit/JSONMLTest.java
@@ -986,4 +986,70 @@ public void testToJSONObjectMaxNestingDepthWithValidFittingXML() {
}
}
+ /**
+ * Tests that malformed XML causing type mismatch throws JSONException.
+ * Previously threw ClassCastException when parse() returned String instead of JSONArray.
+ * Related to issue #1034
+ */
+ @Test(expected = JSONException.class)
+ public void testMalformedXMLThrowsJSONExceptionNotClassCast() {
+ // This malformed XML causes parse() to return wrong type
+ byte[] data = {0x3c, 0x0a, 0x2f, (byte)0xff, (byte)0xff, (byte)0xff,
+ (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+ (byte)0xff, 0x3e, 0x42};
+ String xmlStr = new String(data);
+ JSONML.toJSONArray(xmlStr);
+ }
+
+ /**
+ * Tests that type mismatch in toJSONObject throws JSONException.
+ * Validates safe type casting in toJSONObject methods.
+ */
+ @Test
+ public void testToJSONObjectTypeMismatch() {
+ // Create XML that would cause parse() to return wrong type
+ String xmlStr = "<\n/\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff>B";
+ try {
+ JSONML.toJSONObject(xmlStr);
+ fail("Expected JSONException for type mismatch");
+ } catch (ClassCastException e) {
+ fail("Should throw JSONException, not ClassCastException");
+ } catch (JSONException e) {
+ // Expected - verify it's about type mismatch
+ assertTrue("Exception message should mention type error",
+ e.getMessage().contains("Expected") || e.getMessage().contains("got"));
+ }
+ }
+
+ /**
+ * Tests that valid XML still works correctly after the fix.
+ * Ensures the type checking doesn't break normal operation.
+ */
+ @Test
+ public void testValidXMLStillWorks() {
+ String xmlStr = "- value
";
+ try {
+ JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
+ assertNotNull("JSONArray should not be null", jsonArray);
+ assertEquals("root", jsonArray.getString(0));
+ } catch (Exception e) {
+ fail("Valid XML should not throw exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Tests that valid XML to JSONObject still works correctly.
+ */
+ @Test
+ public void testValidXMLToJSONObjectStillWorks() {
+ String xmlStr = "- content
";
+ try {
+ JSONObject jsonObject = JSONML.toJSONObject(xmlStr);
+ assertNotNull("JSONObject should not be null", jsonObject);
+ assertEquals("root", jsonObject.getString("tagName"));
+ } catch (Exception e) {
+ fail("Valid XML should not throw exception: " + e.getMessage());
+ }
+ }
+
}