Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions src/main/java/org/json/JSONML.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand All @@ -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));
}


Expand Down
66 changes: 66 additions & 0 deletions src/test/java/org/json/junit/JSONMLTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "<root><item>value</item></root>";
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 = "<root attr=\"value\"><item>content</item></root>";
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());
}
}

}
Loading