mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-02 11:05:28 -04:00
Merge pull request #723 from TamasPergerDWP/master
JSONML should be protected from stack overflow exceptions caused by recursion, resolving #722
This commit is contained in:
commit
1275f6809d
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -235,8 +265,8 @@ public class JSONML {
|
||||
* 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
|
||||
* 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.
|
||||
@ -246,7 +276,32 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@ -257,8 +312,32 @@ public class JSONML {
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -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,10 +382,10 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
@ -323,10 +402,32 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a well-formed (but not necessarily valid) XML string into a
|
||||
* JSONObject using the JsonML transform. Each XML tag is represented as
|
||||
@ -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,
|
||||
|
128
src/main/java/org/json/JSONMLParserConfiguration.java
Normal file
128
src/main/java/org/json/JSONMLParserConfiguration.java
Normal file
@ -0,0 +1,128 @@
|
||||
package org.json;
|
||||
/*
|
||||
Public Domain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configuration object for the XML to JSONML parser. The configuration is immutable.
|
||||
*/
|
||||
@SuppressWarnings({""})
|
||||
public class JSONMLParserConfiguration {
|
||||
/**
|
||||
* Used to indicate there's no defined limit to the maximum nesting depth when parsing a XML
|
||||
* document to JSONML.
|
||||
*/
|
||||
public static final int UNDEFINED_MAXIMUM_NESTING_DEPTH = -1;
|
||||
|
||||
/**
|
||||
* The default maximum nesting depth when parsing a XML document to JSONML.
|
||||
*/
|
||||
public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = 512;
|
||||
|
||||
/** 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);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
private boolean keepStrings;
|
||||
|
||||
/**
|
||||
* The maximum nesting depth when parsing a XML document to JSONML.
|
||||
*/
|
||||
private int maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
|
||||
|
||||
/**
|
||||
* Default parser configuration. Does not keep strings (tries to implicitly convert values).
|
||||
*/
|
||||
public JSONMLParserConfiguration() {
|
||||
this.keepStrings = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
private JSONMLParserConfiguration(final boolean keepStrings, final int maxNestingDepth) {
|
||||
this.keepStrings = keepStrings;
|
||||
this.maxNestingDepth = 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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 JSONMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
JSONMLParserConfiguration newConfig = 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 JSONMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
|
||||
JSONMLParserConfiguration newConfig = this.clone();
|
||||
|
||||
if (maxNestingDepth > UNDEFINED_MAXIMUM_NESTING_DEPTH) {
|
||||
newConfig.maxNestingDepth = maxNestingDepth;
|
||||
} else {
|
||||
newConfig.maxNestingDepth = UNDEFINED_MAXIMUM_NESTING_DEPTH;
|
||||
}
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
}
|
@ -98,7 +98,7 @@ public class XML {
|
||||
/**
|
||||
* Replace special characters with XML escapes:
|
||||
*
|
||||
* <pre>{@code
|
||||
* <pre>{@code
|
||||
* & (ampersand) is replaced by &amp;
|
||||
* < (less than) is replaced by &lt;
|
||||
* > (greater than) is replaced by &gt;
|
||||
@ -229,8 +229,12 @@ 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, int currentNestingDepth)
|
||||
throws JSONException {
|
||||
@ -427,7 +431,7 @@ public class XML {
|
||||
context.accumulate(tagName, jsonObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -491,7 +495,7 @@ public class XML {
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* direct copy of {@link JSONObject#stringToNumber(String)} to maintain Android support.
|
||||
*/
|
||||
@ -538,7 +542,7 @@ public class XML {
|
||||
// integer representation.
|
||||
// This will narrow any values to the smallest reasonable Object representation
|
||||
// (Integer, Long, or BigInteger)
|
||||
|
||||
|
||||
// BigInteger down conversion: We use a similar bitLength compare as
|
||||
// BigInteger#intValueExact uses. Increases GC, but objects hold
|
||||
// only what they need. i.e. Less runtime overhead if the value is
|
||||
@ -554,7 +558,7 @@ public class XML {
|
||||
}
|
||||
throw new NumberFormatException("val ["+val+"] is not a valid number.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* direct copy of {@link JSONObject#isDecimalNotation(String)} to maintain Android support.
|
||||
*/
|
||||
@ -572,7 +576,7 @@ public class XML {
|
||||
* name/value pairs and arrays of values. JSON does not does not like to
|
||||
* distinguish between elements and attributes. Sequences of similar
|
||||
* elements are represented as JSONArrays. Content text may be placed in a
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* <[ [ ]]>}</pre>
|
||||
* are ignored.
|
||||
*
|
||||
@ -593,7 +597,7 @@ public class XML {
|
||||
* name/value pairs and arrays of values. JSON does not does not like to
|
||||
* distinguish between elements and attributes. Sequences of similar
|
||||
* elements are represented as JSONArrays. Content text may be placed in a
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* <[ [ ]]>}</pre>
|
||||
* are ignored.
|
||||
*
|
||||
@ -673,7 +677,7 @@ public class XML {
|
||||
* name/value pairs and arrays of values. JSON does not does not like to
|
||||
* distinguish between elements and attributes. Sequences of similar
|
||||
* elements are represented as JSONArrays. Content text may be placed in a
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* <[ [ ]]>}</pre>
|
||||
* are ignored.
|
||||
*
|
||||
@ -699,7 +703,7 @@ public class XML {
|
||||
* name/value pairs and arrays of values. JSON does not does not like to
|
||||
* distinguish between elements and attributes. Sequences of similar
|
||||
* elements are represented as JSONArrays. Content text may be placed in a
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* "content" member. Comments, prologs, DTDs, and <pre>{@code
|
||||
* <[ [ ]]>}</pre>
|
||||
* are ignored.
|
||||
*
|
||||
|
@ -39,14 +39,14 @@ public class XMLParserConfiguration {
|
||||
* 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
|
||||
* processing.
|
||||
*/
|
||||
private String cDataTagName;
|
||||
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
|
||||
* should be kept as attribute(<code>false</code>), or they should be converted to
|
||||
@ -66,8 +66,7 @@ public class XMLParserConfiguration {
|
||||
private Set<String> forceList;
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies the tags whose values should be converted
|
||||
* to arrays
|
||||
* The maximum nesting depth when parsing a XML document to JSON.
|
||||
*/
|
||||
private int maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
|
||||
|
||||
@ -157,15 +156,18 @@ public class XMLParserConfiguration {
|
||||
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
|
||||
* @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 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 ) {
|
||||
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList,
|
||||
final int maxNestingDepth) {
|
||||
this.keepStrings = keepStrings;
|
||||
this.cDataTagName = cDataTagName;
|
||||
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
||||
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
|
||||
this.forceList = Collections.unmodifiableSet(forceList);
|
||||
this.maxNestingDepth = maxNestingDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -183,14 +185,15 @@ 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() {
|
||||
@ -200,10 +203,10 @@ public class XMLParserConfiguration {
|
||||
/**
|
||||
* 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)
|
||||
*
|
||||
*
|
||||
* @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 XMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
@ -216,7 +219,7 @@ public class XMLParserConfiguration {
|
||||
* 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
|
||||
* processing.
|
||||
*
|
||||
*
|
||||
* @return The <code>cDataTagName</code> configuration value.
|
||||
*/
|
||||
public String getcDataTagName() {
|
||||
@ -227,10 +230,10 @@ public class XMLParserConfiguration {
|
||||
* 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
|
||||
* processing.
|
||||
*
|
||||
*
|
||||
* @param newVal
|
||||
* new value to use for the <code>cDataTagName</code> configuration option.
|
||||
*
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
public XMLParserConfiguration withcDataTagName(final String newVal) {
|
||||
@ -243,7 +246,7 @@ public class XMLParserConfiguration {
|
||||
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
|
||||
* should be kept as attribute(<code>false</code>), or they should be converted to
|
||||
* <code>null</code>(<code>true</code>)
|
||||
*
|
||||
*
|
||||
* @return The <code>convertNilAttributeToNull</code> configuration value.
|
||||
*/
|
||||
public boolean isConvertNilAttributeToNull() {
|
||||
@ -254,10 +257,10 @@ public class XMLParserConfiguration {
|
||||
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
|
||||
* should be kept as attribute(<code>false</code>), or they should be converted to
|
||||
* <code>null</code>(<code>true</code>)
|
||||
*
|
||||
*
|
||||
* @param newVal
|
||||
* new value to use for the <code>convertNilAttributeToNull</code> configuration option.
|
||||
*
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal) {
|
||||
@ -295,7 +298,7 @@ public class XMLParserConfiguration {
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
|
||||
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
|
||||
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
|
||||
* @return <code>forceList</code> unmodifiable configuration set.
|
||||
*/
|
||||
public Set<String> getForceList() {
|
||||
@ -304,8 +307,8 @@ public class XMLParserConfiguration {
|
||||
|
||||
/**
|
||||
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
|
||||
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
|
||||
* @param forceList {@code new HashSet<String>()} to parse the provided tags' values as arrays
|
||||
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
|
||||
* @param forceList {@code new HashSet<String>()} to parse the provided tags' values as arrays
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
public XMLParserConfiguration withForceList(final Set<String> forceList) {
|
||||
@ -327,8 +330,9 @@ public class XMLParserConfiguration {
|
||||
/**
|
||||
* 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 go as deep as the maximum call stack size allows. Using any negative value as a
|
||||
* parameter is equivalent to setting no limit to the nesting depth.
|
||||
* 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.
|
||||
*/
|
||||
|
@ -11,19 +11,19 @@ import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests for org.json.JSONML.java
|
||||
*
|
||||
*
|
||||
* Certain inputs are expected to result in exceptions. These tests are
|
||||
* executed first. JSONML provides an API to:
|
||||
* Convert an XML string into a JSONArray or a JSONObject.
|
||||
* Convert an XML string into a JSONArray or a JSONObject.
|
||||
* Convert a JSONArray or JSONObject into an XML string.
|
||||
* Both fromstring and tostring operations operations should be symmetrical
|
||||
* within the limits of JSONML.
|
||||
* within the limits of JSONML.
|
||||
* It should be possible to perform the following operations, which should
|
||||
* result in the original string being recovered, within the limits of the
|
||||
* underlying classes:
|
||||
* Convert a string -> JSONArray -> string -> JSONObject -> string
|
||||
* Convert a string -> JSONObject -> string -> JSONArray -> string
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JSONMLTest {
|
||||
|
||||
@ -56,7 +56,7 @@ public class JSONMLTest {
|
||||
|
||||
/**
|
||||
* Attempts to call JSONML.toString() with a null JSONArray.
|
||||
* Expects a NullPointerException.
|
||||
* Expects a NullPointerException.
|
||||
*/
|
||||
@Test(expected=NullPointerException.class)
|
||||
public void nullJSONXMLException() {
|
||||
@ -69,7 +69,7 @@ public class JSONMLTest {
|
||||
|
||||
/**
|
||||
* Attempts to call JSONML.toString() with a null JSONArray.
|
||||
* Expects a JSONException.
|
||||
* Expects a JSONException.
|
||||
*/
|
||||
@Test
|
||||
public void emptyJSONXMLException() {
|
||||
@ -125,7 +125,7 @@ public class JSONMLTest {
|
||||
"[\"addresses\","+
|
||||
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
|
||||
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
|
||||
// this array has no name
|
||||
// this array has no name
|
||||
"["+
|
||||
"[\"name\"],"+
|
||||
"[\"nocontent\"],"+
|
||||
@ -180,7 +180,7 @@ public class JSONMLTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to transform a malformed XML document
|
||||
* Attempts to transform a malformed XML document
|
||||
* (element tag has a frontslash) to a JSONArray.\
|
||||
* Expects a JSONException
|
||||
*/
|
||||
@ -191,7 +191,7 @@ public class JSONMLTest {
|
||||
* In this case, the XML is invalid because the 'name' element
|
||||
* contains an invalid frontslash.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -216,7 +216,7 @@ public class JSONMLTest {
|
||||
*/
|
||||
@Test
|
||||
public void invalidBangInTagException() {
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -246,7 +246,7 @@ public class JSONMLTest {
|
||||
* In this case, the XML is invalid because an element
|
||||
* starts with '!' and has no closing tag
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -276,7 +276,7 @@ public class JSONMLTest {
|
||||
* In this case, the XML is invalid because an element
|
||||
* has no closing '>'.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -306,7 +306,7 @@ public class JSONMLTest {
|
||||
* In this case, the XML is invalid because an element
|
||||
* has no name after the closing tag '</'.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -336,7 +336,7 @@ public class JSONMLTest {
|
||||
* In this case, the XML is invalid because an element
|
||||
* has '>' after the closing tag '</' and name.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation=\"test.xsd\">\n"+
|
||||
@ -364,9 +364,9 @@ public class JSONMLTest {
|
||||
/**
|
||||
* xmlStr contains XML text which is transformed into a JSONArray.
|
||||
* In this case, the XML is invalid because an element
|
||||
* does not have a complete CDATA string.
|
||||
* does not have a complete CDATA string.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -388,7 +388,7 @@ public class JSONMLTest {
|
||||
/**
|
||||
* Convert an XML document into a JSONArray, then use JSONML.toString()
|
||||
* to convert it into a string. This string is then converted back into
|
||||
* a JSONArray. Both JSONArrays are compared against a control to
|
||||
* a JSONArray. Both JSONArrays are compared against a control to
|
||||
* confirm the contents.
|
||||
*/
|
||||
@Test
|
||||
@ -405,7 +405,7 @@ public class JSONMLTest {
|
||||
* which is used to create a final JSONArray, which is also compared
|
||||
* against the expected JSONArray.
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -414,7 +414,7 @@ public class JSONMLTest {
|
||||
"<nocontent/>>\n"+
|
||||
"</address>\n"+
|
||||
"</addresses>";
|
||||
String expectedStr =
|
||||
String expectedStr =
|
||||
"[\"addresses\","+
|
||||
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
|
||||
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
|
||||
@ -434,12 +434,12 @@ public class JSONMLTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an XML document into a JSONObject. Use JSONML.toString() to
|
||||
* Convert an XML document into a JSONObject. Use JSONML.toString() to
|
||||
* convert it back into a string, and then re-convert it into a JSONObject.
|
||||
* Both JSONObjects are compared against a control JSONObject to confirm
|
||||
* the contents.
|
||||
* <p>
|
||||
* Next convert the XML document into a JSONArray. Use JSONML.toString() to
|
||||
* Next convert the XML document into a JSONArray. Use JSONML.toString() to
|
||||
* convert it back into a string, and then re-convert it into a JSONArray.
|
||||
* Both JSONArrays are compared against a control JSONArray to confirm
|
||||
* the contents.
|
||||
@ -452,23 +452,23 @@ public class JSONMLTest {
|
||||
/**
|
||||
* xmlStr contains XML text which is transformed into a JSONObject,
|
||||
* restored to XML, transformed into a JSONArray, and then restored
|
||||
* to XML again. Both JSONObject and JSONArray should contain the same
|
||||
* to XML again. Both JSONObject and JSONArray should contain the same
|
||||
* information and should produce the same XML, allowing for non-ordered
|
||||
* attributes.
|
||||
*
|
||||
*
|
||||
* Transformation to JSONObject:
|
||||
* The elementName is stored as a string where key="tagName"
|
||||
* Attributes are simply stored as key/value pairs
|
||||
* If the element has either content or child elements, they are stored
|
||||
* in a jsonArray with key="childNodes".
|
||||
*
|
||||
*
|
||||
* Transformation to JSONArray:
|
||||
* 1st entry = elementname
|
||||
* 2nd entry = attributes object (if present)
|
||||
* 3rd entry = content (if present)
|
||||
* 4th entry = child element JSONArrays (if present)
|
||||
*/
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
|
||||
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
|
||||
@ -585,7 +585,7 @@ public class JSONMLTest {
|
||||
"\"tagName\":\"addresses\""+
|
||||
"}";
|
||||
|
||||
String expectedJSONArrayStr =
|
||||
String expectedJSONArrayStr =
|
||||
"["+
|
||||
"\"addresses\","+
|
||||
"{"+
|
||||
@ -645,12 +645,12 @@ public class JSONMLTest {
|
||||
JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
|
||||
Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
|
||||
|
||||
// create a JSON array from the original string and make sure it
|
||||
// create a JSON array from the original string and make sure it
|
||||
// looks as expected
|
||||
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
|
||||
JSONArray expectedJsonArray = new JSONArray(expectedJSONArrayStr);
|
||||
Util.compareActualVsExpectedJsonArrays(jsonArray,expectedJsonArray);
|
||||
|
||||
|
||||
// restore the XML, then make another JSONArray and make sure it
|
||||
// looks as expected
|
||||
String jsonArrayXmlToStr = JSONML.toString(jsonArray);
|
||||
@ -668,14 +668,14 @@ public class JSONMLTest {
|
||||
* Convert an XML document which contains embedded comments into
|
||||
* a JSONArray. Use JSONML.toString() to turn it into a string, then
|
||||
* reconvert it into a JSONArray. Compare both JSONArrays to a control
|
||||
* JSONArray to confirm the contents.
|
||||
* JSONArray to confirm the contents.
|
||||
* <p>
|
||||
* This test shows how XML comments are handled.
|
||||
*/
|
||||
@Test
|
||||
public void commentsInXML() {
|
||||
|
||||
String xmlStr =
|
||||
String xmlStr =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
|
||||
"<!-- this is a comment -->\n"+
|
||||
"<addresses>\n"+
|
||||
@ -734,7 +734,7 @@ public class JSONMLTest {
|
||||
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",\"1\"],[\"id\",\"00\"],[\"id\",\"0\"],[\"item\",{\"id\":\"01\"}],[\"title\",\"True\"]]";
|
||||
final JSONArray json = JSONML.toJSONArray(originalXml,true);
|
||||
assertEquals(expectedJsonString, json.toString());
|
||||
|
||||
|
||||
final String reverseXml = JSONML.toString(json);
|
||||
assertEquals(originalXml, reverseXml);
|
||||
}
|
||||
@ -749,7 +749,7 @@ public class JSONMLTest {
|
||||
final String revertedXml = JSONML.toString(jsonArray);
|
||||
assertEquals(revertedXml, originalXml);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* JSON string cannot be reverted to original xml. See test result in
|
||||
* comment below.
|
||||
@ -770,7 +770,7 @@ public class JSONMLTest {
|
||||
// 1. Our XML parser does not handle generic HTML entities, only valid XML entities. Hence
|
||||
// or other HTML specific entities would fail on reversability
|
||||
// 2. Our JSON implementation for storing the XML attributes uses the standard unordered map.
|
||||
// This means that <tag attr1="v1" attr2="v2" /> can not be reversed reliably.
|
||||
// This means that <tag attr1="v1" attr2="v2" /> can not be reversed reliably.
|
||||
//
|
||||
// /**
|
||||
// * Test texts taken from jsonml.org. Currently our implementation FAILS this conversion but shouldn't.
|
||||
@ -783,13 +783,13 @@ public class JSONMLTest {
|
||||
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"\u00A0\",[\"span\",{ \"style\" : \"background-color:maroon\" },\"\u00A9\"],\"\u00A0\"]]]";
|
||||
// final JSONArray json = JSONML.toJSONArray(originalXml,true);
|
||||
// final String actualJsonString = json.toString();
|
||||
//
|
||||
//
|
||||
// final String reverseXml = JSONML.toString(json);
|
||||
// assertNotEquals(originalXml, reverseXml);
|
||||
//
|
||||
// assertNotEquals(expectedJsonString, actualJsonString);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Test texts taken from jsonml.org but modified to have XML entities only.
|
||||
// */
|
||||
@ -799,15 +799,15 @@ public class JSONMLTest {
|
||||
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"&\",[\"span\",{ \"style\" : \"background-color:maroon\" },\">\"],\"<\"]]]";
|
||||
// final JSONArray jsonML = JSONML.toJSONArray(originalXml,true);
|
||||
// final String actualJsonString = jsonML.toString();
|
||||
//
|
||||
//
|
||||
// final String reverseXml = JSONML.toString(jsonML);
|
||||
// // currently not equal because the hashing of the attribute objects makes the attribute
|
||||
// // order not happen the same way twice
|
||||
// // order not happen the same way twice
|
||||
// assertEquals(originalXml, reverseXml);
|
||||
//
|
||||
// assertEquals(expectedJsonString, actualJsonString);
|
||||
// }
|
||||
|
||||
|
||||
@Test (timeout = 6000)
|
||||
public void testIssue484InfinteLoop1() {
|
||||
try {
|
||||
@ -819,11 +819,11 @@ public class JSONMLTest {
|
||||
ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test (timeout = 6000)
|
||||
public void testIssue484InfinteLoop2() {
|
||||
try {
|
||||
String input = "??*\n" +
|
||||
String input = "??*\n" +
|
||||
"??|?CglR??`??>?w??PIlr??D?$?-?o??O?*??{OD?Y??`2a????NM?bq?:O?>S$?J?B.gUK?m\b??zE???!v]???????c??????h???s???g???`?qbi??:Zl?)?}1^??k?0??:$V?$?Ovs(}J??????2;gQ????Tg?K?`?h%c?hmGA?<!C*?9?~?t?)??,zA???S}?Q??.q?j????]";
|
||||
JSONML.toJSONObject(input);
|
||||
fail("Exception expected for invalid JSON.");
|
||||
@ -833,4 +833,128 @@ 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 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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user