Skip to content

Commit df2d6f8

Browse files
fix: introduce optional XMLtoJSONMLParserConfiguration parameter for JSONML.toJSONArray(...) functions, to facilitate max nesting depth override.
1 parent a6e412b commit df2d6f8

File tree

2 files changed

+116
-3
lines changed

2 files changed

+116
-3
lines changed

src/main/java/org/json/JSONML.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,55 @@ public static JSONArray toJSONArray(String string, boolean keepStrings) throws J
280280
}
281281

282282

283+
284+
/**
285+
* Convert a well-formed (but not necessarily valid) XML string into a
286+
* JSONArray using the JsonML transform. Each XML tag is represented as
287+
* a JSONArray in which the first element is the tag name. If the tag has
288+
* attributes, then the second element will be JSONObject containing the
289+
* name/value pairs. If the tag contains children, then strings and
290+
* JSONArrays will represent the child tags.
291+
* As opposed to toJSONArray this method does not attempt to convert
292+
* any text node or attribute value to any type
293+
* but just leaves it as a string.
294+
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
295+
* @param string The source string.
296+
* @param config The XML parser configuration:
297+
* XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
298+
* XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
299+
* or numeric values and will instead be left as strings
300+
* @return A JSONArray containing the structured data from the XML string.
301+
* @throws JSONException Thrown on error converting to a JSONArray
302+
*/
303+
public static JSONArray toJSONArray(String string, XMLtoJSONMLParserConfiguration config) throws JSONException {
304+
return (JSONArray)parse(new XMLTokener(string), true, null, config, 0);
305+
}
306+
307+
308+
/**
309+
* Convert a well-formed (but not necessarily valid) XML string into a
310+
* JSONArray using the JsonML transform. Each XML tag is represented as
311+
* a JSONArray in which the first element is the tag name. If the tag has
312+
* attributes, then the second element will be JSONObject containing the
313+
* name/value pairs. If the tag contains children, then strings and
314+
* JSONArrays will represent the child content and tags.
315+
* As opposed to toJSONArray this method does not attempt to convert
316+
* any text node or attribute value to any type
317+
* but just leaves it as a string.
318+
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
319+
* @param x An XMLTokener.
320+
* @param config The XML parser configuration:
321+
* XMLtoJSONMLParserConfiguration.ORIGINAL is the default behaviour;
322+
* XMLtoJSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
323+
* or numeric values and will instead be left as strings
324+
* @return A JSONArray containing the structured data from the XML string.
325+
* @throws JSONException Thrown on error converting to a JSONArray
326+
*/
327+
public static JSONArray toJSONArray(XMLTokener x, XMLtoJSONMLParserConfiguration config) throws JSONException {
328+
return (JSONArray)parse(x, true, null, config, 0);
329+
}
330+
331+
283332
/**
284333
* Convert a well-formed (but not necessarily valid) XML string into a
285334
* JSONArray using the JsonML transform. Each XML tag is represented as

src/test/java/org/json/junit/JSONMLTest.java

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,71 @@ public void testIssue484InfinteLoop2() {
835835
}
836836

837837
@Test
838-
public void testMaxNestingDepthOf42IsRespected() {
838+
public void testToJSONArrayMaxNestingDepthOf42IsRespected() {
839+
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
840+
841+
final int maxNestingDepth = 42;
842+
843+
try {
844+
JSONML.toJSONArray(wayTooLongMalformedXML, XMLtoJSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
845+
846+
fail("Expecting a JSONException");
847+
} catch (JSONException e) {
848+
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
849+
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
850+
}
851+
}
852+
853+
854+
@Test
855+
public void testToJSONArrayMaxNestingDepthIsRespectedWithValidXML() {
856+
final String perfectlyFineXML = "<Test>\n" +
857+
" <employee>\n" +
858+
" <name>sonoo</name>\n" +
859+
" <salary>56000</salary>\n" +
860+
" <married>true</married>\n" +
861+
" </employee>\n" +
862+
"</Test>\n";
863+
864+
final int maxNestingDepth = 1;
865+
866+
try {
867+
JSONML.toJSONArray(perfectlyFineXML, XMLtoJSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
868+
869+
fail("Expecting a JSONException");
870+
} catch (JSONException e) {
871+
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
872+
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
873+
}
874+
}
875+
876+
@Test
877+
public void testToJSONArrayMaxNestingDepthWithValidFittingXML() {
878+
final String perfectlyFineXML = "<Test>\n" +
879+
" <employee>\n" +
880+
" <name>sonoo</name>\n" +
881+
" <salary>56000</salary>\n" +
882+
" <married>true</married>\n" +
883+
" </employee>\n" +
884+
"</Test>\n";
885+
886+
final int maxNestingDepth = 3;
887+
888+
try {
889+
JSONML.toJSONArray(perfectlyFineXML, XMLtoJSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
890+
} catch (JSONException e) {
891+
e.printStackTrace();
892+
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
893+
"parameter of the XMLtoJSONMLParserConfiguration used");
894+
}
895+
}
896+
897+
898+
899+
900+
901+
@Test
902+
public void testToJSONObjectMaxNestingDepthOf42IsRespected() {
839903
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
840904

841905
final int maxNestingDepth = 42;
@@ -851,7 +915,7 @@ public void testMaxNestingDepthOf42IsRespected() {
851915
}
852916

853917
@Test
854-
public void testMaxNestingDepthIsRespectedWithValidXML() {
918+
public void testToJSONObjectMaxNestingDepthIsRespectedWithValidXML() {
855919
final String perfectlyFineXML = "<Test>\n" +
856920
" <employee>\n" +
857921
" <name>sonoo</name>\n" +
@@ -873,7 +937,7 @@ public void testMaxNestingDepthIsRespectedWithValidXML() {
873937
}
874938

875939
@Test
876-
public void testMaxNestingDepthWithValidFittingXML() {
940+
public void testToJSONObjectMaxNestingDepthWithValidFittingXML() {
877941
final String perfectlyFineXML = "<Test>\n" +
878942
" <employee>\n" +
879943
" <name>sonoo</name>\n" +

0 commit comments

Comments
 (0)