mirror of
https://github.com/stleary/JSON-java.git
synced 2026-01-24 00:03:17 -05:00
Compare commits
34 Commits
bb1138762a
...
pre-releas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c048b36516 | ||
|
|
f6e5bfa2db | ||
|
|
084b24cbe7 | ||
|
|
22ccf1b8e5 | ||
|
|
133c0cc75f | ||
|
|
0578285036 | ||
|
|
48fb5261fe | ||
|
|
8353b9c3f0 | ||
|
|
fe22b242b5 | ||
|
|
7eca507d13 | ||
|
|
e1eabc9c27 | ||
|
|
0d436d92e2 | ||
|
|
45bcba518f | ||
|
|
47fb49b6a8 | ||
|
|
0df034c9fd | ||
|
|
f0a05e6911 | ||
|
|
24093491a8 | ||
|
|
1275f6809d | ||
|
|
9234eab00a | ||
|
|
72f4c3e646 | ||
|
|
df2d6f8363 | ||
|
|
a6e412bded | ||
|
|
2391d248cc | ||
|
|
401495ae86 | ||
|
|
448e204186 | ||
|
|
eb56704e68 | ||
|
|
651511f500 | ||
|
|
a14cb12c85 | ||
|
|
f566a1d9ee | ||
|
|
5920eca2d7 | ||
|
|
3b097d051a | ||
|
|
4e630e58a4 | ||
|
|
b732188e4e | ||
|
|
5369442671 |
@@ -8,7 +8,7 @@ JSON in Java [package org.json]
|
||||
|
||||
[](https://mvnrepository.com/artifact/org.json/json)
|
||||
|
||||
**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar)**
|
||||
**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20230618/json-20230618.jar)**
|
||||
|
||||
|
||||
# Overview
|
||||
|
||||
@@ -5,6 +5,10 @@ and artifactId "json". For example:
|
||||
[https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav](https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav)
|
||||
|
||||
~~~
|
||||
20230618 Final release with Java 1.6 compatibility. Future releases will require Java 1.8 or greater.
|
||||
|
||||
20230227 Fix for CVE-2022-45688 and recent commits
|
||||
|
||||
20220924 New License - public domain, and some minor updates
|
||||
|
||||
20220320 Wrap StackOverflow with JSONException
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
||||
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20220924</version>
|
||||
<version>20230618</version>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>JSON in Java</name>
|
||||
|
||||
@@ -27,7 +27,32 @@ public class JSONML {
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja,
|
||||
boolean keepStrings
|
||||
boolean keepStrings,
|
||||
int currentNestingDepth
|
||||
) throws JSONException {
|
||||
return parse(x,arrayForm, ja,
|
||||
keepStrings ? JSONMLParserConfiguration.KEEP_STRINGS : JSONMLParserConfiguration.ORIGINAL,
|
||||
currentNestingDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse XML values and store them in a JSONArray.
|
||||
* @param x The XMLTokener containing the source string.
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @param config The parser configuration:
|
||||
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* JSONMLParserConfiguration.KEEP_STRINGS means Don't type-convert text nodes and attribute values.
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException if a parsing error occurs
|
||||
*/
|
||||
private static Object parse(
|
||||
XMLTokener x,
|
||||
boolean arrayForm,
|
||||
JSONArray ja,
|
||||
JSONMLParserConfiguration config,
|
||||
int currentNestingDepth
|
||||
) throws JSONException {
|
||||
String attribute;
|
||||
char c;
|
||||
@@ -152,7 +177,7 @@ public class JSONML {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
|
||||
newjo.accumulate(attribute, config.isKeepStrings() ? ((String)token) :XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
@@ -181,7 +206,12 @@ public class JSONML {
|
||||
if (token != XML.GT) {
|
||||
throw x.syntaxError("Misshaped tag");
|
||||
}
|
||||
closeTag = (String)parse(x, arrayForm, newja, keepStrings);
|
||||
|
||||
if (currentNestingDepth == config.getMaxNestingDepth()) {
|
||||
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
|
||||
}
|
||||
|
||||
closeTag = (String)parse(x, arrayForm, newja, config, currentNestingDepth + 1);
|
||||
if (closeTag != null) {
|
||||
if (!closeTag.equals(tagName)) {
|
||||
throw x.syntaxError("Mismatched '" + tagName +
|
||||
@@ -203,7 +233,7 @@ public class JSONML {
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
||||
? (config.isKeepStrings() ? XML.unescape((String)token) : XML.stringToValue((String)token))
|
||||
: token);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +254,7 @@ public class JSONML {
|
||||
* @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, false);
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, JSONMLParserConfiguration.ORIGINAL, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +276,56 @@ public class JSONML {
|
||||
* @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);
|
||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param string The source string.
|
||||
* @param config The parser configuration:
|
||||
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONArray using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONArray in which the first element is the tag name. If the tag has
|
||||
* attributes, then the second element will be JSONObject containing the
|
||||
* name/value pairs. If the tag contains children, then strings and
|
||||
* JSONArrays will represent the child content and tags.
|
||||
* As opposed to toJSONArray this method does not attempt to convert
|
||||
* any text node or attribute value to any type
|
||||
* but just leaves it as a string.
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param x An XMLTokener.
|
||||
* @param config The parser configuration:
|
||||
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONArray containing the structured data from the XML string.
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@@ -268,7 +347,7 @@ public class JSONML {
|
||||
* @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);
|
||||
return (JSONArray)parse(x, true, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +364,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONArray
|
||||
*/
|
||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||
return (JSONArray)parse(x, true, null, false);
|
||||
return (JSONArray)parse(x, true, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -303,7 +382,7 @@ public class JSONML {
|
||||
* @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);
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -323,7 +402,29 @@ public class JSONML {
|
||||
* @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);
|
||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param string The XML source text.
|
||||
* @param config The parser configuration:
|
||||
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@@ -341,7 +442,7 @@ public class JSONML {
|
||||
* @throws JSONException Thrown on error converting to a JSONObject
|
||||
*/
|
||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||
return (JSONObject)parse(x, false, null, false);
|
||||
return (JSONObject)parse(x, false, null, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +462,29 @@ public class JSONML {
|
||||
* @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);
|
||||
return (JSONObject)parse(x, false, null, keepStrings, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
* a JSONObject with a "tagName" property. If the tag has attributes, then
|
||||
* the attributes will be in the JSONObject as properties. If the tag
|
||||
* contains children, the object will have a "childNodes" property which
|
||||
* will be an array of strings and JsonML JSONObjects.
|
||||
|
||||
* Comments, prologs, DTDs, and <pre>{@code <[ [ ]]>}</pre> are ignored.
|
||||
* @param x An XMLTokener of the XML source text.
|
||||
* @param config The parser configuration:
|
||||
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
|
||||
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
|
||||
* or numeric values and will instead be left as strings
|
||||
* @return A JSONObject containing the structured data from the XML string.
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
||||
@@ -442,6 +565,7 @@ public class JSONML {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the JSONML transformation, making an XML text from a JSONObject.
|
||||
* The JSONObject must contain a "tagName" property. If it has children,
|
||||
|
||||
67
src/main/java/org/json/JSONMLParserConfiguration.java
Normal file
67
src/main/java/org/json/JSONMLParserConfiguration.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package org.json;
|
||||
/*
|
||||
Public Domain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration object for the XML to JSONML parser. The configuration is immutable.
|
||||
*/
|
||||
@SuppressWarnings({""})
|
||||
public class JSONMLParserConfiguration extends ParserConfiguration {
|
||||
|
||||
/**
|
||||
* We can override the default maximum nesting depth if needed.
|
||||
*/
|
||||
public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH;
|
||||
|
||||
/** Original Configuration of the XML to JSONML Parser. */
|
||||
public static final JSONMLParserConfiguration ORIGINAL
|
||||
= new JSONMLParserConfiguration();
|
||||
/** Original configuration of the XML to JSONML Parser except that values are kept as strings. */
|
||||
public static final JSONMLParserConfiguration KEEP_STRINGS
|
||||
= new JSONMLParserConfiguration().withKeepStrings(true);
|
||||
|
||||
/**
|
||||
* Default parser configuration. Does not keep strings (tries to implicitly convert values).
|
||||
*/
|
||||
public JSONMLParserConfiguration() {
|
||||
super();
|
||||
this.maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the parser string processing and use the default CDATA Tag Name as "content".
|
||||
* @param keepStrings <code>true</code> to parse all values as string.
|
||||
* <code>false</code> to try and convert XML string values into a JSON value.
|
||||
* @param maxNestingDepth <code>int</code> to limit the nesting depth
|
||||
*/
|
||||
protected JSONMLParserConfiguration(final boolean keepStrings, final int maxNestingDepth) {
|
||||
super(keepStrings, maxNestingDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a new instance of the same configuration.
|
||||
*/
|
||||
@Override
|
||||
protected JSONMLParserConfiguration clone() {
|
||||
// future modifications to this method should always ensure a "deep"
|
||||
// clone in the case of collections. i.e. if a Map is added as a configuration
|
||||
// item, a new map instance should be created and if possible each value in the
|
||||
// map should be cloned as well. If the values of the map are known to also
|
||||
// be immutable, then a shallow clone of the map is acceptable.
|
||||
return new JSONMLParserConfiguration(
|
||||
this.keepStrings,
|
||||
this.maxNestingDepth
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
return super.withKeepStrings(newVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
|
||||
return super.withMaxNestingDepth(maxNestingDepth);
|
||||
}
|
||||
}
|
||||
@@ -1290,11 +1290,7 @@ public class JSONObject {
|
||||
if (val == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
final double doubleValue = val.doubleValue();
|
||||
// if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
|
||||
// return defaultValue;
|
||||
// }
|
||||
return doubleValue;
|
||||
return val.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package org.json;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/*
|
||||
Public Domain.
|
||||
@@ -61,7 +57,7 @@ public class JSONTokener {
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) {
|
||||
this(new InputStreamReader(inputStream));
|
||||
this(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
|
||||
}
|
||||
|
||||
|
||||
@@ -522,4 +518,10 @@ public class JSONTokener {
|
||||
return " at " + this.index + " [character " + this.character + " line " +
|
||||
this.line + "]";
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if(reader!=null){
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
112
src/main/java/org/json/ParserConfiguration.java
Normal file
112
src/main/java/org/json/ParserConfiguration.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package org.json;
|
||||
/*
|
||||
Public Domain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration base object for parsers. The configuration is immutable.
|
||||
*/
|
||||
@SuppressWarnings({""})
|
||||
public class ParserConfiguration {
|
||||
/**
|
||||
* Used to indicate there's no defined limit to the maximum nesting depth when parsing a document.
|
||||
*/
|
||||
public static final int UNDEFINED_MAXIMUM_NESTING_DEPTH = -1;
|
||||
|
||||
/**
|
||||
* The default maximum nesting depth when parsing a document.
|
||||
*/
|
||||
public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = 512;
|
||||
|
||||
/**
|
||||
* Specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
*/
|
||||
protected boolean keepStrings;
|
||||
|
||||
/**
|
||||
* The maximum nesting depth when parsing a document.
|
||||
*/
|
||||
protected int maxNestingDepth;
|
||||
|
||||
public ParserConfiguration() {
|
||||
this.keepStrings = false;
|
||||
this.maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
|
||||
}
|
||||
|
||||
protected ParserConfiguration(final boolean keepStrings, final int maxNestingDepth) {
|
||||
this.keepStrings = keepStrings;
|
||||
this.maxNestingDepth = maxNestingDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a new instance of the same configuration.
|
||||
*/
|
||||
@Override
|
||||
protected ParserConfiguration clone() {
|
||||
// future modifications to this method should always ensure a "deep"
|
||||
// clone in the case of collections. i.e. if a Map is added as a configuration
|
||||
// item, a new map instance should be created and if possible each value in the
|
||||
// map should be cloned as well. If the values of the map are known to also
|
||||
// be immutable, then a shallow clone of the map is acceptable.
|
||||
return new ParserConfiguration(
|
||||
this.keepStrings,
|
||||
this.maxNestingDepth
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSONML, specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
*
|
||||
* @return The <code>keepStrings</code> configuration value.
|
||||
*/
|
||||
public boolean isKeepStrings() {
|
||||
return this.keepStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSONML, specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
*
|
||||
* @param newVal
|
||||
* new value to use for the <code>keepStrings</code> configuration option.
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
public <T extends ParserConfiguration> T withKeepStrings(final boolean newVal) {
|
||||
T newConfig = (T)this.clone();
|
||||
newConfig.keepStrings = newVal;
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum nesting depth that the parser will descend before throwing an exception
|
||||
* when parsing the XML into JSONML.
|
||||
* @return the maximum nesting depth set for this configuration
|
||||
*/
|
||||
public int getMaxNestingDepth() {
|
||||
return maxNestingDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the maximum nesting depth that the parser will descend before throwing an exception
|
||||
* when parsing the XML into JSONML. The default max nesting depth is 512, which means the parser
|
||||
* will throw a JsonException if the maximum depth is reached.
|
||||
* Using any negative value as a parameter is equivalent to setting no limit to the nesting depth,
|
||||
* which means the parses will go as deep as the maximum call stack size allows.
|
||||
* @param maxNestingDepth the maximum nesting depth allowed to the XML parser
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
public <T extends ParserConfiguration> T withMaxNestingDepth(int maxNestingDepth) {
|
||||
T newConfig = (T)this.clone();
|
||||
|
||||
if (maxNestingDepth > UNDEFINED_MAXIMUM_NESTING_DEPTH) {
|
||||
newConfig.maxNestingDepth = maxNestingDepth;
|
||||
} else {
|
||||
newConfig.maxNestingDepth = UNDEFINED_MAXIMUM_NESTING_DEPTH;
|
||||
}
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
}
|
||||
@@ -229,10 +229,14 @@ public class XML {
|
||||
* The JSONObject that will include the new material.
|
||||
* @param name
|
||||
* The tag name.
|
||||
* @param config
|
||||
* The XML parser configuration.
|
||||
* @param currentNestingDepth
|
||||
* The current nesting depth.
|
||||
* @return true if the close tag is processed.
|
||||
* @throws JSONException
|
||||
* @throws JSONException Thrown if any parsing error occurs.
|
||||
*/
|
||||
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config)
|
||||
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, int currentNestingDepth)
|
||||
throws JSONException {
|
||||
char c;
|
||||
int i;
|
||||
@@ -402,7 +406,11 @@ public class XML {
|
||||
|
||||
} else if (token == LT) {
|
||||
// Nested element
|
||||
if (parse(x, jsonObject, tagName, config)) {
|
||||
if (currentNestingDepth == config.getMaxNestingDepth()) {
|
||||
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
|
||||
}
|
||||
|
||||
if (parse(x, jsonObject, tagName, config, currentNestingDepth + 1)) {
|
||||
if (config.getForceList().contains(tagName)) {
|
||||
// Force the value to be an array
|
||||
if (jsonObject.length() == 0) {
|
||||
@@ -655,7 +663,7 @@ public class XML {
|
||||
while (x.more()) {
|
||||
x.skipPast("<");
|
||||
if(x.more()) {
|
||||
parse(x, jo, null, config);
|
||||
parse(x, jo, null, config, 0);
|
||||
}
|
||||
}
|
||||
return jo;
|
||||
|
||||
@@ -15,7 +15,13 @@ import java.util.Set;
|
||||
* @author AylwardJ
|
||||
*/
|
||||
@SuppressWarnings({""})
|
||||
public class XMLParserConfiguration {
|
||||
public class XMLParserConfiguration extends ParserConfiguration {
|
||||
|
||||
/**
|
||||
* The default maximum nesting depth when parsing a XML document to JSON.
|
||||
*/
|
||||
// public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = 512; // We could override
|
||||
|
||||
/** Original Configuration of the XML Parser. */
|
||||
public static final XMLParserConfiguration ORIGINAL
|
||||
= new XMLParserConfiguration();
|
||||
@@ -23,12 +29,6 @@ public class XMLParserConfiguration {
|
||||
public static final XMLParserConfiguration KEEP_STRINGS
|
||||
= new XMLParserConfiguration().withKeepStrings(true);
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
*/
|
||||
private boolean keepStrings;
|
||||
|
||||
/**
|
||||
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
|
||||
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
|
||||
@@ -59,7 +59,7 @@ public class XMLParserConfiguration {
|
||||
* values), and the CDATA Tag Name is "content".
|
||||
*/
|
||||
public XMLParserConfiguration () {
|
||||
this.keepStrings = false;
|
||||
super();
|
||||
this.cDataTagName = "content";
|
||||
this.convertNilAttributeToNull = false;
|
||||
this.xsiTypeMap = Collections.emptyMap();
|
||||
@@ -106,7 +106,7 @@ public class XMLParserConfiguration {
|
||||
*/
|
||||
@Deprecated
|
||||
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
|
||||
this.keepStrings = keepStrings;
|
||||
super(keepStrings, DEFAULT_MAXIMUM_NESTING_DEPTH);
|
||||
this.cDataTagName = cDataTagName;
|
||||
this.convertNilAttributeToNull = false;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ public class XMLParserConfiguration {
|
||||
*/
|
||||
@Deprecated
|
||||
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
|
||||
this.keepStrings = keepStrings;
|
||||
super(keepStrings, DEFAULT_MAXIMUM_NESTING_DEPTH);
|
||||
this.cDataTagName = cDataTagName;
|
||||
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
||||
}
|
||||
@@ -141,10 +141,12 @@ public class XMLParserConfiguration {
|
||||
* @param xsiTypeMap <code>new HashMap<String, XMLXsiTypeConverter<?>>()</code> to parse values with attribute
|
||||
* xsi:type="integer" as integer, xsi:type="string" as string
|
||||
* @param forceList <code>new HashSet<String>()</code> to parse the provided tags' values as arrays
|
||||
* @param maxNestingDepth <code>int</code> to limit the nesting depth
|
||||
*/
|
||||
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
|
||||
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList ) {
|
||||
this.keepStrings = keepStrings;
|
||||
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList,
|
||||
final int maxNestingDepth) {
|
||||
super(keepStrings, maxNestingDepth);
|
||||
this.cDataTagName = cDataTagName;
|
||||
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
||||
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
|
||||
@@ -166,20 +168,11 @@ public class XMLParserConfiguration {
|
||||
this.cDataTagName,
|
||||
this.convertNilAttributeToNull,
|
||||
this.xsiTypeMap,
|
||||
this.forceList
|
||||
this.forceList,
|
||||
this.maxNestingDepth
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
*
|
||||
* @return The <code>keepStrings</code> configuration value.
|
||||
*/
|
||||
public boolean isKeepStrings() {
|
||||
return this.keepStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
|
||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||
@@ -189,10 +182,9 @@ public class XMLParserConfiguration {
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
@Override
|
||||
public XMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
XMLParserConfiguration newConfig = this.clone();
|
||||
newConfig.keepStrings = newVal;
|
||||
return newConfig;
|
||||
return super.withKeepStrings(newVal);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,4 +289,18 @@ public class XMLParserConfiguration {
|
||||
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the maximum nesting depth that the parser will descend before throwing an exception
|
||||
* when parsing the XML into JSON. The default max nesting depth is 512, which means the parser
|
||||
* will throw a JsonException if the maximum depth is reached.
|
||||
* Using any negative value as a parameter is equivalent to setting no limit to the nesting depth,
|
||||
* which means the parses will go as deep as the maximum call stack size allows.
|
||||
* @param maxNestingDepth the maximum nesting depth allowed to the XML parser
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
@Override
|
||||
public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
|
||||
return super.withMaxNestingDepth(maxNestingDepth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ Public Domain.
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -833,4 +833,157 @@ public class JSONMLTest {
|
||||
ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSONArrayMaxNestingDepthOf42IsRespected() {
|
||||
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
|
||||
|
||||
final int maxNestingDepth = 42;
|
||||
|
||||
try {
|
||||
JSONML.toJSONArray(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testToJSONArrayMaxNestingDepthIsRespectedWithValidXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 1;
|
||||
|
||||
try {
|
||||
JSONML.toJSONArray(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSONArrayMaxNestingDepthWithValidFittingXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 3;
|
||||
|
||||
try {
|
||||
JSONML.toJSONArray(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
|
||||
"parameter of the JSONMLParserConfiguration used");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testToJSONObjectMaxDefaultNestingDepthIsRespected() {
|
||||
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
|
||||
|
||||
try {
|
||||
JSONML.toJSONObject(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL);
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + JSONMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSONObjectUnlimitedNestingDepthIsPossible() {
|
||||
int actualDepth = JSONMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH +10;
|
||||
final String deeperThanDefaultMax = new String(new char[actualDepth]).replace("\0", "<a>") +
|
||||
"value" +
|
||||
new String(new char[actualDepth]).replace("\0", "</a>");
|
||||
|
||||
try {
|
||||
JSONML.toJSONObject(deeperThanDefaultMax, JSONMLParserConfiguration.ORIGINAL
|
||||
.withMaxNestingDepth(JSONMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
fail("XML document should be parsed beyond the default maximum depth if maxNestingDepth " +
|
||||
"parameter is set to -1 in JSONMLParserConfiguration");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testToJSONObjectMaxNestingDepthOf42IsRespected() {
|
||||
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
|
||||
|
||||
final int maxNestingDepth = 42;
|
||||
|
||||
try {
|
||||
JSONML.toJSONObject(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSONObjectMaxNestingDepthIsRespectedWithValidXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 1;
|
||||
|
||||
try {
|
||||
JSONML.toJSONObject(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJSONObjectMaxNestingDepthWithValidFittingXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 3;
|
||||
|
||||
try {
|
||||
JSONML.toJSONObject(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
|
||||
"parameter of the JSONMLParserConfiguration used");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -313,4 +313,16 @@ public class JSONTokenerTest {
|
||||
assertEquals(0, t2.next());
|
||||
assertFalse(t2.more());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoClose(){
|
||||
Reader reader = new StringReader("some test string");
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(reader);
|
||||
tokener.close();
|
||||
tokener.next();
|
||||
} catch (Exception exception){
|
||||
assertEquals("Stream closed", exception.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,6 +1052,29 @@ public class XMLConfigurationTest {
|
||||
Util.compareActualVsExpectedJsonObjects(jsonObject, expetedJsonObject);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxNestingDepthIsSet() {
|
||||
XMLParserConfiguration xmlParserConfiguration = XMLParserConfiguration.ORIGINAL;
|
||||
|
||||
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
|
||||
|
||||
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(42);
|
||||
|
||||
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 42);
|
||||
|
||||
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(0);
|
||||
|
||||
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 0);
|
||||
|
||||
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(-31415926);
|
||||
|
||||
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
|
||||
|
||||
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(Integer.MIN_VALUE);
|
||||
|
||||
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method, given an input string and expected result,
|
||||
* convert to JSONObject and compare actual to expected result.
|
||||
|
||||
@@ -1111,6 +1111,7 @@ public class XMLTest {
|
||||
"}" ;
|
||||
JSONObject jsonObject = new JSONObject(str);
|
||||
String actualIndentedXmlString = XML.toString(jsonObject, 1);
|
||||
JSONObject actualJsonObject = XML.toJSONObject(actualIndentedXmlString);
|
||||
String expected = "<success>true</success>\n" +
|
||||
"<response>\n" +
|
||||
" <dateTimeISO>2022-10-05T00:00:00+03:00</dateTimeISO>\n" +
|
||||
@@ -1170,7 +1171,8 @@ public class XMLTest {
|
||||
" <timestamp>1664917200</timestamp>\n" +
|
||||
"</response>\n" +
|
||||
"<error>null</error>\n";
|
||||
assertEquals(actualIndentedXmlString, expected);
|
||||
JSONObject expectedJsonObject = XML.toJSONObject(expected);
|
||||
assertTrue(expectedJsonObject.similar(actualJsonObject));
|
||||
|
||||
|
||||
}
|
||||
@@ -1183,6 +1185,7 @@ public class XMLTest {
|
||||
" }}";
|
||||
JSONObject jsonObject = new JSONObject(str);
|
||||
String actual = XML.toString(jsonObject, "Test", 2);
|
||||
JSONObject actualJsonObject = XML.toJSONObject(actual);
|
||||
String expected = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
@@ -1190,7 +1193,8 @@ public class XMLTest {
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
assertEquals(actual, expected);
|
||||
JSONObject expectedJsonObject = XML.toJSONObject(expected);
|
||||
assertTrue(expectedJsonObject.similar(actualJsonObject));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1201,6 +1205,7 @@ public class XMLTest {
|
||||
"] ";
|
||||
JSONArray jsonObject = new JSONArray(str);
|
||||
String actual = XML.toString(jsonObject, 2);
|
||||
JSONObject actualJsonObject = XML.toJSONObject(actual);
|
||||
String expected = "<array>\n" +
|
||||
" <name>Ram</name>\n" +
|
||||
" <email>Ram@gmail.com</email>\n" +
|
||||
@@ -1209,7 +1214,8 @@ public class XMLTest {
|
||||
" <name>Bob</name>\n" +
|
||||
" <email>bob32@gmail.com</email>\n" +
|
||||
"</array>\n";
|
||||
assertEquals(actual, expected);
|
||||
JSONObject expectedJsonObject = XML.toJSONObject(expected);
|
||||
assertTrue(expectedJsonObject.similar(actualJsonObject));
|
||||
|
||||
|
||||
}
|
||||
@@ -1247,6 +1253,65 @@ public class XMLTest {
|
||||
fail("file writer error: " +e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxNestingDepthOf42IsRespected() {
|
||||
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
|
||||
|
||||
final int maxNestingDepth = 42;
|
||||
|
||||
try {
|
||||
XML.toJSONObject(wayTooLongMalformedXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxNestingDepthIsRespectedWithValidXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 1;
|
||||
|
||||
try {
|
||||
XML.toJSONObject(perfectlyFineXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
|
||||
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxNestingDepthWithValidFittingXML() {
|
||||
final String perfectlyFineXML = "<Test>\n" +
|
||||
" <employee>\n" +
|
||||
" <name>sonoo</name>\n" +
|
||||
" <salary>56000</salary>\n" +
|
||||
" <married>true</married>\n" +
|
||||
" </employee>\n" +
|
||||
"</Test>\n";
|
||||
|
||||
final int maxNestingDepth = 3;
|
||||
|
||||
try {
|
||||
XML.toJSONObject(perfectlyFineXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
|
||||
"parameter of the XMLParserConfiguration used");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user