entry : entrySet()) {
String name = entry.getKey();
Object valueThis = entry.getValue();
- Object valueOther = ((JSONObject)other).get(name);
- if(valueThis == valueOther) {
- continue;
+ Object valueOther = ((JSONObject) other).get(name);
+ if (valueThis == valueOther) {
+ continue;
}
- if(valueThis == null) {
- return false;
+ if (valueThis == null) {
+ return false;
}
if (valueThis instanceof JSONObject) {
- if (!((JSONObject)valueThis).similar(valueOther)) {
+ if (!((JSONObject) valueThis).similar(valueOther)) {
return false;
}
} else if (valueThis instanceof JSONArray) {
- if (!((JSONArray)valueThis).similar(valueOther)) {
+ if (!((JSONArray) valueThis).similar(valueOther)) {
return false;
}
} else if (valueThis instanceof Number && valueOther instanceof Number) {
- if (!isNumberSimilar((Number)valueThis, (Number)valueOther)) {
- return false;
+ if (!isNumberSimilar((Number) valueThis, (Number) valueOther)) {
+ return false;
}
} else if (valueThis instanceof JSONString && valueOther instanceof JSONString) {
if (!((JSONString) valueThis).toJSONString().equals(((JSONString) valueOther).toJSONString())) {
- return false;
+ return false;
}
} else if (!valueThis.equals(valueOther)) {
return false;
@@ -2439,7 +2107,6 @@ public boolean similar(Object other) {
/**
* Compares two numbers to see if they are similar.
- *
* If either of the numbers are Double or Float instances, then they are checked to have
* a finite value. If either value is not finite (NaN or ±infinity), then this
* function will always return false. If both numbers are finite, they are first checked
@@ -2452,6 +2119,7 @@ public boolean similar(Object other) {
* @param r the right value to compare. Can not be null.
* @return true if the numbers are similar, false otherwise.
*/
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
static boolean isNumberSimilar(Number l, Number r) {
if (!numberIsFinite(l) || !numberIsFinite(r)) {
// non-finite numbers are never similar
@@ -2460,10 +2128,10 @@ static boolean isNumberSimilar(Number l, Number r) {
// if the classes are the same and implement Comparable
// then use the built in compare first.
- if(l.getClass().equals(r.getClass()) && l instanceof Comparable) {
- @SuppressWarnings({ "rawtypes", "unchecked" })
- int compareTo = ((Comparable)l).compareTo(r);
- return compareTo==0;
+ if (l.getClass().equals(r.getClass()) && l instanceof Comparable) {
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ int compareTo = ((Comparable) l).compareTo(r);
+ return compareTo == 0;
}
// BigDecimal should be able to handle all of our number types that we support through
@@ -2477,13 +2145,11 @@ static boolean isNumberSimilar(Number l, Number r) {
return lBigDecimal.compareTo(rBigDecimal) == 0;
}
+ @SuppressWarnings("BooleanMethodIsAlwaysInverted")
private static boolean numberIsFinite(Number n) {
if (n instanceof Double && (((Double) n).isInfinite() || ((Double) n).isNaN())) {
return false;
- } else if (n instanceof Float && (((Float) n).isInfinite() || ((Float) n).isNaN())) {
- return false;
- }
- return true;
+ } else return !(n instanceof Float) || (!((Float) n).isInfinite() && !((Float) n).isNaN());
}
/**
@@ -2501,11 +2167,9 @@ protected static boolean isDecimalNotation(final String val) {
* Try to convert a string into a number, boolean, or null. If the string
* can't be converted, return the string.
*
- * @param string
- * A String. can not be null.
+ * @param string A String. can not be null.
* @return A simple JSON value.
- * @throws NullPointerException
- * Thrown if the string is null.
+ * @throws NullPointerException Thrown if the string is null.
*/
// Changes to this method must be copied to the corresponding method in
// the XML class to keep full support for Android
@@ -2548,7 +2212,7 @@ public static Object stringToValue(String string) {
* @param val value to convert
* @return Number representation of the value.
* @throws NumberFormatException thrown if the value is not a valid number. A public
- * caller should catch this and wrap it in a {@link JSONException} if applicable.
+ * caller should catch this and wrap it in a {@link JSONException} if applicable.
*/
protected static Number stringToNumber(final String val) throws NumberFormatException {
char initial = val.charAt(0);
@@ -2560,34 +2224,34 @@ protected static Number stringToNumber(final String val) throws NumberFormatExce
// keep that by forcing a decimal.
try {
BigDecimal bd = new BigDecimal(val);
- if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) {
- return Double.valueOf(-0.0);
+ if (initial == '-' && BigDecimal.ZERO.compareTo(bd) == 0) {
+ return -0.0;
}
return bd;
} catch (NumberFormatException retryAsDouble) {
// this is to support "Hex Floats" like this: 0x1.0P-1074
try {
Double d = Double.valueOf(val);
- if(d.isNaN() || d.isInfinite()) {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
+ if (d.isNaN() || d.isInfinite()) {
+ throw new NumberFormatException("val [" + val + "] is not a valid number.");
}
return d;
} catch (NumberFormatException ignore) {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
+ throw new NumberFormatException("val [" + val + "] is not a valid number.");
}
}
}
// block items like 00 01 etc. Java number parsers treat these as Octal.
- if(initial == '0' && val.length() > 1) {
+ if (initial == '0' && val.length() > 1) {
char at1 = val.charAt(1);
- if(at1 >= '0' && at1 <= '9') {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
+ if (at1 >= '0' && at1 <= '9') {
+ throw new NumberFormatException("val [" + val + "] is not a valid number.");
}
} else if (initial == '-' && val.length() > 2) {
char at1 = val.charAt(1);
char at2 = val.charAt(2);
- if(at1 == '0' && at2 >= '0' && at2 <= '9') {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
+ if (at1 == '0' && at2 >= '0' && at2 <= '9') {
+ throw new NumberFormatException("val [" + val + "] is not a valid number.");
}
}
// integer representation.
@@ -2599,24 +2263,22 @@ protected static Number stringToNumber(final String val) throws NumberFormatExce
// only what they need. i.e. Less runtime overhead if the value is
// long lived.
BigInteger bi = new BigInteger(val);
- if(bi.bitLength() <= 31){
- return Integer.valueOf(bi.intValue());
+ if (bi.bitLength() <= 31) {
+ return bi.intValue();
}
- if(bi.bitLength() <= 63){
- return Long.valueOf(bi.longValue());
+ if (bi.bitLength() <= 63) {
+ return bi.longValue();
}
return bi;
}
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
+ throw new NumberFormatException("val [" + val + "] is not a valid number.");
}
/**
* Throw an exception if the object is a NaN or infinite number.
*
- * @param o
- * The object to test.
- * @throws JSONException
- * If o is a non-finite number.
+ * @param o The object to test.
+ * @throws JSONException If o is a non-finite number.
*/
public static void testValidity(Object o) throws JSONException {
if (o instanceof Number && !numberIsFinite((Number) o)) {
@@ -2628,12 +2290,10 @@ public static void testValidity(Object o) throws JSONException {
* Produce a JSONArray containing the values of the members of this
* JSONObject.
*
- * @param names
- * A JSONArray containing a list of key strings. This determines
- * the sequence of the values in the result.
+ * @param names A JSONArray containing a list of key strings. This determines
+ * the sequence of the values in the result.
* @return A JSONArray of values.
- * @throws JSONException
- * If any of the values are non-finite numbers.
+ * @throws JSONException If any of the values are non-finite numbers.
*/
public JSONArray toJSONArray(JSONArray names) throws JSONException {
if (names == null || names.isEmpty()) {
@@ -2641,7 +2301,7 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException {
}
JSONArray ja = new JSONArray();
for (int i = 0; i < names.length(); i += 1) {
- ja.put(this.opt(names.getString(i)));
+ ja.put(opt(names.getString(i)));
}
return ja;
}
@@ -2655,14 +2315,14 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException {
*
*
* @return a printable, displayable, portable, transmittable representation
- * of the object, beginning with { (left
- * brace) and ending with } (right
- * brace) .
+ * of the object, beginning with { (left
+ * brace) and ending with } (right
+ * brace) .
*/
@Override
public String toString() {
try {
- return this.toString(0);
+ return toString(0);
} catch (Exception e) {
return null;
}
@@ -2685,22 +2345,19 @@ public String toString() {
* Warning: This method assumes that the data structure is acyclical.
*
*
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
+ * @param indentFactor The number of spaces to add to each level of indentation.
* @return a printable, displayable, portable, transmittable representation
- * of the object, beginning with { (left
- * brace) and ending with } (right
- * brace) .
- * @throws JSONException
- * If the object contains an invalid number.
+ * of the object, beginning with { (left
+ * brace) and ending with } (right
+ * brace) .
+ * @throws JSONException If the object contains an invalid number.
*/
- @SuppressWarnings("resource")
public String toString(int indentFactor) throws JSONException {
// 6 characters are the minimum to serialise a key value pair e.g.: "k":1,
// and we don't want to oversize the initial capacity
int initialSize = map.size() * 6;
Writer w = new StringBuilderWriter(Math.max(initialSize, 16));
- return this.write(w, indentFactor, 0).toString();
+ return write(w, indentFactor, 0).toString();
}
/**
@@ -2718,20 +2375,18 @@ public String toString(int indentFactor) throws JSONException {
*
* Warning: This method assumes that the data structure is acyclical.
*
- * @param value
- * The value to be serialized.
+ * @param value The value to be serialized.
* @return a printable, displayable, transmittable representation of the
- * object, beginning with { (left
- * brace) and ending with } (right
- * brace) .
- * @throws JSONException
- * If the value is or contains an invalid number.
+ * object, beginning with { (left
+ * brace) and ending with } (right
+ * brace) .
+ * @throws JSONException If the value is or contains an invalid number.
*/
public static String valueToString(Object value) throws JSONException {
- // moves the implementation to JSONWriter as:
- // 1. It makes more sense to be part of the writer class
- // 2. For Android support this method is not available. By implementing it in the Writer
- // Android users can use the writer with the built in Android JSONObject implementation.
+ // moves the implementation to JSONWriter as:
+ // 1. It makes more sense to be part of the writer class
+ // 2. For Android support this method is not available. By implementing it in the Writer
+ // Android users can use the writer with the built in Android JSONObject implementation.
return JSONWriter.valueToString(value);
}
@@ -2743,39 +2398,14 @@ public static String valueToString(Object value) throws JSONException {
* one of the java packages, turn it into a string. And if it doesn't, try
* to wrap it in a JSONObject. If the wrapping fails, then null is returned.
*
- * @param object
- * The object to wrap
+ * @param object The object to wrap
* @return The wrapped value
*/
public static Object wrap(Object object) {
return wrap(object, null);
}
- /**
- * Wrap an object, if necessary. If the object is null, return the NULL
- * object. If it is an array or collection, wrap it in a JSONArray. If it is
- * a map, wrap it in a JSONObject. If it is a standard property (Double,
- * String, et al) then it is already wrapped. Otherwise, if it comes from
- * one of the java packages, turn it into a string. And if it doesn't, try
- * to wrap it in a JSONObject. If the wrapping fails, then null is returned.
- *
- * @param object
- * The object to wrap
- * @param recursionDepth
- * Variable for tracking the count of nested object creations.
- * @param jsonParserConfiguration
- * Variable to pass parser custom configuration for json parsing.
- * @return The wrapped value
- */
- static Object wrap(Object object, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
- return wrap(object, null, recursionDepth, jsonParserConfiguration);
- }
-
private static Object wrap(Object object, Set objectsRecord) {
- return wrap(object, objectsRecord, 0, new JSONParserConfiguration());
- }
-
- private static Object wrap(Object object, Set objectsRecord, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
try {
if (NULL.equals(object)) {
return NULL;
@@ -2791,16 +2421,14 @@ private static Object wrap(Object object, Set objectsRecord, int recursi
return object;
}
- if (object instanceof Collection) {
- Collection> coll = (Collection>) object;
- return new JSONArray(coll, recursionDepth, jsonParserConfiguration);
+ if (object instanceof Collection> coll) {
+ return new JSONArray(coll);
}
if (object.getClass().isArray()) {
return new JSONArray(object);
}
- if (object instanceof Map) {
- Map, ?> map = (Map, ?>) object;
- return new JSONObject(map, recursionDepth, jsonParserConfiguration);
+ if (object instanceof Map, ?> map) {
+ return new JSONObject(map);
}
Package objectPackage = object.getClass().getPackage();
String objectPackageName = objectPackage != null ? objectPackage
@@ -2814,8 +2442,7 @@ private static Object wrap(Object object, Set objectsRecord, int recursi
return new JSONObject(object, objectsRecord);
}
return new JSONObject(object);
- }
- catch (JSONException exception) {
+ } catch (JSONException exception) {
throw exception;
} catch (Exception exception) {
return null;
@@ -2828,18 +2455,18 @@ private static Object wrap(Object object, Set objectsRecord, int recursi
*
* Warning: This method assumes that the data structure is acyclical.
*
+ *
* @param writer the writer object
* @return The writer.
* @throws JSONException if a called function has an error
*/
public Writer write(Writer writer) throws JSONException {
- return this.write(writer, 0, 0);
+ return write(writer, 0, 0);
}
- @SuppressWarnings("resource")
- static final Writer writeValue(Writer writer, Object value,
- int indentFactor, int indent) throws JSONException, IOException {
- if (value == null || value.equals(null)) {
+ static Writer writeValue(Writer writer, Object value,
+ int indentFactor, int indent) throws JSONException, IOException {
+ if (value == null) {
writer.write("null");
} else if (value instanceof JSONString) {
// JSONString must be checked first, so it can overwrite behaviour of other types below
@@ -2857,7 +2484,7 @@ static final Writer writeValue(Writer writer, Object value,
} else if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
final String numberAsString = numberToString((Number) value);
- if(NUMBER_PATTERN.matcher(numberAsString).matches()) {
+ if (NUMBER_PATTERN.matcher(numberAsString).matches()) {
writer.write(numberAsString);
} else {
// The Number value is not a valid JSON number.
@@ -2867,16 +2494,14 @@ static final Writer writeValue(Writer writer, Object value,
} else if (value instanceof Boolean) {
writer.write(value.toString());
} else if (value instanceof Enum>) {
- writer.write(quote(((Enum>)value).name()));
+ writer.write(quote(((Enum>) value).name()));
} else if (value instanceof JSONObject) {
((JSONObject) value).write(writer, indentFactor, indent);
} else if (value instanceof JSONArray) {
((JSONArray) value).write(writer, indentFactor, indent);
- } else if (value instanceof Map) {
- Map, ?> map = (Map, ?>) value;
+ } else if (value instanceof Map, ?> map) {
new JSONObject(map).write(writer, indentFactor, indent);
- } else if (value instanceof Collection) {
- Collection> coll = (Collection>) value;
+ } else if (value instanceof Collection> coll) {
new JSONArray(coll).write(writer, indentFactor, indent);
} else if (value.getClass().isArray()) {
new JSONArray(value).write(writer, indentFactor, indent);
@@ -2886,7 +2511,7 @@ static final Writer writeValue(Writer writer, Object value,
return writer;
}
- static final void indent(Writer writer, int indent) throws IOException {
+ static void indent(Writer writer, int indent) throws IOException {
for (int i = 0; i < indent; i += 1) {
writer.write(' ');
}
@@ -2909,40 +2534,36 @@ static final void indent(Writer writer, int indent) throws IOException {
* Warning: This method assumes that the data structure is acyclical.
*
*
- * @param writer
- * Writes the serialized JSON
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
- * @param indent
- * The indentation of the top level.
+ * @param writer Writes the serialized JSON
+ * @param indentFactor The number of spaces to add to each level of indentation.
+ * @param indent The indentation of the top level.
* @return The writer.
* @throws JSONException if a called function has an error or a write error
- * occurs
+ * occurs
*/
- @SuppressWarnings("resource")
public Writer write(Writer writer, int indentFactor, int indent)
throws JSONException {
try {
boolean needsComma = false;
- final int length = this.length();
+ final int length = length();
writer.write('{');
if (length == 1) {
- final Entry entry = this.entrySet().iterator().next();
+ final Entry entry = entrySet().iterator().next();
final String key = entry.getKey();
writer.write(quote(key));
writer.write(':');
if (indentFactor > 0) {
writer.write(' ');
}
- try{
+ try {
writeValue(writer, entry.getValue(), indentFactor, indent);
} catch (Exception e) {
throw new JSONException("Unable to write JSONObject value for key: " + key, e);
}
} else if (length != 0) {
final int newIndent = indent + indentFactor;
- for (final Entry entry : this.entrySet()) {
+ for (final Entry entry : entrySet()) {
if (needsComma) {
writer.write(',');
}
@@ -2985,8 +2606,8 @@ public Writer write(Writer writer, int indentFactor, int indent)
* @return a java.util.Map containing the entries of this object
*/
public Map toMap() {
- Map results = new HashMap();
- for (Entry entry : this.entrySet()) {
+ Map results = new HashMap<>();
+ for (Entry entry : entrySet()) {
Object value;
if (entry.getValue() == null || NULL.equals(entry.getValue())) {
value = null;
@@ -3004,9 +2625,10 @@ public Map toMap() {
/**
* Create a new JSONException in a common format for incorrect conversions.
- * @param key name of the key
+ *
+ * @param key name of the key
* @param valueType the type of value being coerced to
- * @param cause optional cause of the coercion failure
+ * @param cause optional cause of the coercion failure
* @return JSONException that can be thrown.
*/
private static JSONException wrongValueFormatException(
@@ -3014,14 +2636,14 @@ private static JSONException wrongValueFormatException(
String valueType,
Object value,
Throwable cause) {
- if(value == null) {
+ if (value == null) {
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + " (null)."
, cause);
}
// don't try to toString collections or known object types that could be large.
- if(value instanceof Map || value instanceof Iterable || value instanceof JSONObject) {
+ if (value instanceof Map || value instanceof Iterable || value instanceof JSONObject) {
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value.getClass() + ")."
, cause);
@@ -3033,12 +2655,13 @@ private static JSONException wrongValueFormatException(
/**
* Create a new JSONException in a common format for recursive object definition.
+ *
* @param key name of the key
* @return JSONException that can be thrown.
*/
private static JSONException recursivelyDefinedObjectException(String key) {
return new JSONException(
- "JavaBean object contains recursively defined member variable of key " + quote(key)
+ "JavaBean object contains recursively defined member variable of key " + quote(key)
);
}
}
diff --git a/src/main/java/org/json/JSONParserConfiguration.java b/src/main/java/org/json/JSONParserConfiguration.java
deleted file mode 100644
index 0cfa2eaef..000000000
--- a/src/main/java/org/json/JSONParserConfiguration.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package org.json;
-
-/**
- * Configuration object for the JSON parser. The configuration is immutable.
- */
-public class JSONParserConfiguration extends ParserConfiguration {
- /**
- * Used to indicate whether to overwrite duplicate key or not.
- */
- private boolean overwriteDuplicateKey;
-
- /**
- * Used to indicate whether to convert java null values to JSONObject.NULL or ignoring the entry when converting java maps.
- */
- private boolean useNativeNulls;
-
- /**
- * Configuration with the default values.
- */
- public JSONParserConfiguration() {
- super();
- this.overwriteDuplicateKey = false;
- // DO NOT DELETE THE FOLLOWING LINE -- it is used for strictMode testing
- // this.strictMode = true;
- }
-
- /**
- * This flag, when set to true, instructs the parser to enforce strict mode when parsing JSON text.
- * Garbage chars at the end of the doc, unquoted string, and single-quoted strings are all disallowed.
- */
- private boolean strictMode;
-
- @Override
- protected JSONParserConfiguration clone() {
- JSONParserConfiguration clone = new JSONParserConfiguration();
- clone.overwriteDuplicateKey = overwriteDuplicateKey;
- clone.strictMode = strictMode;
- clone.maxNestingDepth = maxNestingDepth;
- clone.keepStrings = keepStrings;
- clone.useNativeNulls = useNativeNulls;
- return clone;
- }
-
- /**
- * Defines the maximum nesting depth that the parser will descend before throwing an exception
- * when parsing a map into JSONObject or parsing a {@link java.util.Collection} instance into
- * JSONArray. The default max nesting depth is 512, which means the parser will throw a JsonException
- * if the maximum depth is reached.
- *
- * @param maxNestingDepth the maximum nesting depth allowed to the JSON parser
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- @SuppressWarnings("unchecked")
- @Override
- public JSONParserConfiguration withMaxNestingDepth(final int maxNestingDepth) {
- JSONParserConfiguration clone = this.clone();
- clone.maxNestingDepth = maxNestingDepth;
-
- return clone;
- }
-
- /**
- * Controls the parser's behavior when meeting duplicate keys.
- * If set to false, the parser will throw a JSONException when meeting a duplicate key.
- * Or the duplicate key's value will be overwritten.
- *
- * @param overwriteDuplicateKey defines should the parser overwrite duplicate keys.
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public JSONParserConfiguration withOverwriteDuplicateKey(final boolean overwriteDuplicateKey) {
- JSONParserConfiguration clone = this.clone();
- clone.overwriteDuplicateKey = overwriteDuplicateKey;
-
- return clone;
- }
-
- /**
- * Controls the parser's behavior when meeting Java null values while converting maps.
- * If set to true, the parser will put a JSONObject.NULL into the resulting JSONObject.
- * Or the map entry will be ignored.
- *
- * @param useNativeNulls defines if the parser should convert null values in Java maps
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public JSONParserConfiguration withUseNativeNulls(final boolean useNativeNulls) {
- JSONParserConfiguration clone = this.clone();
- clone.useNativeNulls = useNativeNulls;
-
- return clone;
- }
-
- /**
- * Sets the strict mode configuration for the JSON parser with default true value
- *
- * When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character
- * immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
- * JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
- * @return a new JSONParserConfiguration instance with the updated strict mode setting
- */
- public JSONParserConfiguration withStrictMode() {
- return withStrictMode(true);
- }
-
- /**
- * Sets the strict mode configuration for the JSON parser.
- *
- * When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character
- * immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
- * JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
- *
- * @param mode a boolean value indicating whether strict mode should be enabled or not
- * @return a new JSONParserConfiguration instance with the updated strict mode setting
- */
- public JSONParserConfiguration withStrictMode(final boolean mode) {
- JSONParserConfiguration clone = this.clone();
- clone.strictMode = mode;
-
- return clone;
- }
-
- /**
- * The parser's behavior when meeting duplicate keys, controls whether the parser should
- * overwrite duplicate keys or not.
- *
- * @return The overwriteDuplicateKey configuration value.
- */
- public boolean isOverwriteDuplicateKey() {
- return this.overwriteDuplicateKey;
- }
-
- /**
- * The parser's behavior when meeting a null value in a java map, controls whether the parser should
- * write a JSON entry with a null value (isUseNativeNulls() == true)
- * or ignore that map entry (isUseNativeNulls() == false).
- *
- * @return The useNativeNulls configuration value.
- */
- public boolean isUseNativeNulls() {
- return this.useNativeNulls;
- }
-
-
- /**
- * The parser throws an Exception when strict mode is true and tries to parse invalid JSON characters.
- * Otherwise, the parser is more relaxed and might tolerate some invalid characters.
- *
- * @return the current strict mode setting.
- */
- public boolean isStrictMode() {
- return this.strictMode;
- }
-}
diff --git a/src/main/java/org/json/JSONPointer.java b/src/main/java/org/json/JSONPointer.java
index 34066c1aa..f663262ef 100644
--- a/src/main/java/org/json/JSONPointer.java
+++ b/src/main/java/org/json/JSONPointer.java
@@ -4,7 +4,6 @@
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
-import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -16,7 +15,6 @@
/**
* A JSON Pointer is a simple query language defined for JSON documents by
* RFC 6901 .
- *
* In a nutshell, JSONPointer allows the user to navigate into a JSON document
* using strings, and retrieve targeted objects, like a simple form of XPATH.
* Path segments are separated by the '/' char, which signifies the root of
@@ -36,82 +34,6 @@ public class JSONPointer {
// used for URL encoding and decoding
private static final String ENCODING = "utf-8";
- /**
- * This class allows the user to build a JSONPointer in steps, using
- * exactly one segment in each step.
- */
- public static class Builder {
-
- /**
- * Constructs a new Builder object.
- */
- public Builder() {
- }
-
- // Segments for the eventual JSONPointer string
- private final List refTokens = new ArrayList();
-
- /**
- * Creates a {@code JSONPointer} instance using the tokens previously set using the
- * {@link #append(String)} method calls.
- * @return a JSONPointer object
- */
- public JSONPointer build() {
- return new JSONPointer(this.refTokens);
- }
-
- /**
- * Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
- *
- * Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
- * argument of this method MUST NOT be escaped. If you want to query the property called
- * {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
- * need to escape it as {@code "a~0b"}.
- *
- * @param token the new token to be appended to the list
- * @return {@code this}
- * @throws NullPointerException if {@code token} is null
- */
- public Builder append(String token) {
- if (token == null) {
- throw new NullPointerException("token cannot be null");
- }
- this.refTokens.add(token);
- return this;
- }
-
- /**
- * Adds an integer to the reference token list. Although not necessarily, mostly this token will
- * denote an array index.
- *
- * @param arrayIndex the array index to be added to the token list
- * @return {@code this}
- */
- public Builder append(int arrayIndex) {
- this.refTokens.add(String.valueOf(arrayIndex));
- return this;
- }
- }
-
- /**
- * Static factory method for {@link Builder}. Example usage:
- *
- *
- * JSONPointer pointer = JSONPointer.builder()
- * .append("obj")
- * .append("other~key").append("another/key")
- * .append("\"")
- * .append(0)
- * .build();
- *
- *
- * @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
- * {@link Builder#append(String)} calls.
- */
- public static Builder builder() {
- return new Builder();
- }
-
// Segments for the JSONPointer string
private final List refTokens;
@@ -124,9 +46,6 @@ public static Builder builder() {
* @throws IllegalArgumentException if {@code pointer} is not a valid JSON pointer
*/
public JSONPointer(final String pointer) {
- if (pointer == null) {
- throw new NullPointerException("pointer cannot be null");
- }
if (pointer.isEmpty() || "#".equals(pointer)) {
this.refTokens = Collections.emptyList();
return;
@@ -139,45 +58,33 @@ public JSONPointer(final String pointer) {
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
- } else if (pointer.startsWith("/")) {
+ } else if (pointer.charAt(0) == '/') {
refs = pointer.substring(1);
} else {
throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'");
}
- this.refTokens = new ArrayList();
+ refTokens = new ArrayList<>();
int slashIdx = -1;
- int prevSlashIdx = 0;
+ int prevSlashIdx;
do {
prevSlashIdx = slashIdx + 1;
slashIdx = refs.indexOf('/', prevSlashIdx);
if(prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) {
// found 2 slashes in a row ( obj//next )
// or single slash at the end of a string ( obj/test/ )
- this.refTokens.add("");
+ refTokens.add("");
} else if (slashIdx >= 0) {
final String token = refs.substring(prevSlashIdx, slashIdx);
- this.refTokens.add(unescape(token));
+ refTokens.add(unescape(token));
} else {
// last item after separator, or no separator at all.
final String token = refs.substring(prevSlashIdx);
- this.refTokens.add(unescape(token));
+ refTokens.add(unescape(token));
}
} while (slashIdx >= 0);
// using split does not take into account consecutive separators or "ending nulls"
- //for (String token : refs.split("/")) {
- // this.refTokens.add(unescape(token));
- //}
}
- /**
- * Constructs a new JSONPointer instance with the provided list of reference tokens.
- *
- * @param refTokens A list of strings representing the reference tokens for the JSON Pointer.
- * Each token identifies a step in the path to the targeted value.
- */
- public JSONPointer(List refTokens) {
- this.refTokens = new ArrayList(refTokens);
- }
/**
* @see rfc6901 section 3
@@ -197,11 +104,11 @@ private static String unescape(String token) {
* @throws JSONPointerException if an error occurs during evaluation
*/
public Object queryFrom(Object document) throws JSONPointerException {
- if (this.refTokens.isEmpty()) {
+ if (refTokens.isEmpty()) {
return document;
}
Object current = document;
- for (String token : this.refTokens) {
+ for (String token : refTokens) {
if (current instanceof JSONObject) {
current = ((JSONObject) current).opt(unescape(token));
} else if (current instanceof JSONArray) {
@@ -228,7 +135,7 @@ private static Object readByIndexToken(Object current, String indexToken) throws
JSONArray currentArr = (JSONArray) current;
if (index >= currentArr.length()) {
throw new JSONPointerException(format("index %s is out of bounds - the array has %d elements", indexToken,
- Integer.valueOf(currentArr.length())));
+ currentArr.length()));
}
try {
return currentArr.get(index);
@@ -266,22 +173,4 @@ private static String escape(String token) {
return token.replace("~", "~0")
.replace("/", "~1");
}
-
- /**
- * Returns a string representing the JSONPointer path value using URI
- * fragment identifier representation
- * @return a uri fragment string
- */
- public String toURIFragment() {
- try {
- StringBuilder rval = new StringBuilder("#");
- for (String token : this.refTokens) {
- rval.append('/').append(URLEncoder.encode(token, ENCODING));
- }
- return rval.toString();
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
}
diff --git a/src/main/java/org/json/JSONPointerException.java b/src/main/java/org/json/JSONPointerException.java
index dc5a25ad6..e38ecb902 100644
--- a/src/main/java/org/json/JSONPointerException.java
+++ b/src/main/java/org/json/JSONPointerException.java
@@ -4,6 +4,8 @@
Public Domain.
*/
+import java.io.Serial;
+
/**
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs
* during evaluating a pointer.
@@ -12,6 +14,7 @@
* @version 2016-05-13
*/
public class JSONPointerException extends JSONException {
+ @Serial
private static final long serialVersionUID = 8872944667561856751L;
/**
diff --git a/src/main/java/org/json/JSONString.java b/src/main/java/org/json/JSONString.java
index cd8d1847d..ed6595926 100644
--- a/src/main/java/org/json/JSONString.java
+++ b/src/main/java/org/json/JSONString.java
@@ -19,5 +19,5 @@ public interface JSONString {
*
* @return A strictly syntactically correct JSON text.
*/
- public String toJSONString();
+ String toJSONString();
}
diff --git a/src/main/java/org/json/JSONStringer.java b/src/main/java/org/json/JSONStringer.java
deleted file mode 100644
index 2f6cf9ed8..000000000
--- a/src/main/java/org/json/JSONStringer.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package org.json;
-
-/*
-Public Domain.
-*/
-
-import java.io.StringWriter;
-
-/**
- * JSONStringer provides a quick and convenient way of producing JSON text.
- * The texts produced strictly conform to JSON syntax rules. No whitespace is
- * added, so the results are ready for transmission or storage. Each instance of
- * JSONStringer can produce one JSON text.
- *
- * A JSONStringer instance provides a value method for appending
- * values to the
- * text, and a key
- * method for adding keys before values in objects. There are array
- * and endArray methods that make and bound array values, and
- * object and endObject methods which make and bound
- * object values. All of these methods return the JSONWriter instance,
- * permitting cascade style. For example,
- * myString = new JSONStringer()
- * .object()
- * .key("JSON")
- * .value("Hello, World!")
- * .endObject()
- * .toString(); which produces the string
- * {"JSON":"Hello, World!"}
- *
- * The first method called must be array or object.
- * There are no methods for adding commas or colons. JSONStringer adds them for
- * you. Objects and arrays can be nested up to 200 levels deep.
- *
- * This can sometimes be easier than using a JSONObject to build a string.
- * @author JSON.org
- * @version 2015-12-09
- */
-public class JSONStringer extends JSONWriter {
- /**
- * Make a fresh JSONStringer. It can be used to build one JSON text.
- */
- public JSONStringer() {
- super(new StringWriter());
- }
-
- /**
- * Return the JSON text. This method is used to obtain the product of the
- * JSONStringer instance. It will return null if there was a
- * problem in the construction of the JSON text (such as the calls to
- * array were not properly balanced with calls to
- * endArray).
- * @return The JSON text.
- */
- @Override
- public String toString() {
- return this.mode == 'd' ? this.writer.toString() : null;
- }
-}
diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java
index a90d51ae3..1873469e4 100644
--- a/src/main/java/org/json/JSONTokener.java
+++ b/src/main/java/org/json/JSONTokener.java
@@ -1,7 +1,6 @@
package org.json;
import java.io.*;
-import java.nio.charset.Charset;
/*
Public Domain.
@@ -11,77 +10,56 @@
* A JSONTokener takes a source string and extracts characters and tokens from
* it. It is used by the JSONObject and JSONArray constructors to parse
* JSON source strings.
+ *
* @author JSON.org
* @version 2014-05-03
*/
public class JSONTokener {
- /** current read character position on the current line. */
+ /**
+ * current read character position on the current line.
+ */
private long character;
- /** flag to indicate if the end of the input has been found. */
+ /**
+ * flag to indicate if the end of the input has been found.
+ */
private boolean eof;
- /** current read index of the input. */
+ /**
+ * current read index of the input.
+ */
private long index;
- /** current line of the input. */
+ /**
+ * current line of the input.
+ */
private long line;
- /** previous character read from the input. */
- private char previous;
- /** Reader for the input. */
- private final Reader reader;
- /** flag to indicate that a previous character was requested. */
- private boolean usePrevious;
- /** the number of characters read in the previous line. */
- private long characterPreviousLine;
-
- // access to this object is required for strict mode checking
- private JSONParserConfiguration jsonParserConfiguration;
-
/**
- * Construct a JSONTokener from a Reader. The caller must close the Reader.
- *
- * @param reader the source.
+ * previous character read from the input.
*/
- public JSONTokener(Reader reader) {
- this(reader, new JSONParserConfiguration());
- }
-
+ private char previous;
/**
- * Construct a JSONTokener from a Reader with a given JSONParserConfiguration. The caller must close the Reader.
- *
- * @param reader the source.
- * @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
- *
+ * Reader for the input.
*/
- public JSONTokener(Reader reader, JSONParserConfiguration jsonParserConfiguration) {
- this.jsonParserConfiguration = jsonParserConfiguration;
- this.reader = reader.markSupported()
- ? reader
- : new BufferedReader(reader);
- this.eof = false;
- this.usePrevious = false;
- this.previous = 0;
- this.index = 0;
- this.character = 1;
- this.characterPreviousLine = 0;
- this.line = 1;
- }
-
+ private final Reader reader;
/**
- * Construct a JSONTokener from an InputStream. The caller must close the input stream.
- * @param inputStream The source.
+ * flag to indicate that a previous character was requested.
*/
- public JSONTokener(InputStream inputStream) {
- this(inputStream, new JSONParserConfiguration());
- }
-
+ private boolean usePrevious;
/**
- * Construct a JSONTokener from an InputStream. The caller must close the input stream.
- * @param inputStream The source.
- * @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
+ * the number of characters read in the previous line.
*/
- public JSONTokener(InputStream inputStream, JSONParserConfiguration jsonParserConfiguration) {
- this(new InputStreamReader(inputStream, Charset.forName("UTF-8")), jsonParserConfiguration);
- }
+ private long characterPreviousLine;
+ public JSONTokener(Reader reader) {
+ this.reader = reader.markSupported()
+ ? reader
+ : new BufferedReader(reader);
+ eof = false;
+ usePrevious = false;
+ previous = 0;
+ index = 0;
+ character = 1;
+ characterPreviousLine = 0;
+ line = 1;
+ }
/**
* Construct a JSONTokener from a string.
@@ -92,122 +70,34 @@ public JSONTokener(String source) {
this(new StringReader(source));
}
- /**
- * Construct a JSONTokener from an InputStream. The caller must close the input stream.
- * @param source The source.
- * @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
- */
- public JSONTokener(String source, JSONParserConfiguration jsonParserConfiguration) {
- this(new StringReader(source), jsonParserConfiguration);
- }
-
- /**
- * Getter
- * @return jsonParserConfiguration
- */
- public JSONParserConfiguration getJsonParserConfiguration() {
- return jsonParserConfiguration;
- }
-
- /**
- * Setter
- * @param jsonParserConfiguration new value for jsonParserConfiguration
- *
- * @deprecated method should not be used
- */
- @Deprecated
- public void setJsonParserConfiguration(JSONParserConfiguration jsonParserConfiguration) {
- this.jsonParserConfiguration = jsonParserConfiguration;
- }
-
- /**
- * Back up one character. This provides a sort of lookahead capability,
- * so that you can test for a digit or letter before attempting to parse
- * the next number or identifier.
- * @throws JSONException Thrown if trying to step back more than 1 step
- * or if already at the start of the string
- */
public void back() throws JSONException {
- if (this.usePrevious || this.index <= 0) {
- throw new JSONException("Stepping back two steps is not supported");
- }
- this.decrementIndexes();
- this.usePrevious = true;
- this.eof = false;
+ decrementIndexes();
+ usePrevious = true;
+ eof = false;
}
/**
* Decrements the indexes for the {@link #back()} method based on the previous character read.
*/
private void decrementIndexes() {
- this.index--;
- if(this.previous=='\r' || this.previous == '\n') {
- this.line--;
- this.character=this.characterPreviousLine ;
- } else if(this.character > 0){
- this.character--;
+ index--;
+ if (previous == '\r' || previous == '\n') {
+ line--;
+ character = characterPreviousLine;
+ } else if (character > 0) {
+ character--;
}
}
- /**
- * Get the hex value of a character (base16).
- * @param c A character between '0' and '9' or between 'A' and 'F' or
- * between 'a' and 'f'.
- * @return An int between 0 and 15, or -1 if c was not a hex digit.
- */
- public static int dehexchar(char c) {
- if (c >= '0' && c <= '9') {
- return c - '0';
- }
- if (c >= 'A' && c <= 'F') {
- return c - ('A' - 10);
- }
- if (c >= 'a' && c <= 'f') {
- return c - ('a' - 10);
- }
- return -1;
- }
-
/**
* Checks if the end of the input has been reached.
*
* @return true if at the end of the file and we didn't step back
*/
public boolean end() {
- return this.eof && !this.usePrevious;
- }
-
-
- /**
- * Determine if the source string still contains characters that next()
- * can consume.
- * @return true if not yet at the end of the source.
- * @throws JSONException thrown if there is an error stepping forward
- * or backward while checking for more data.
- */
- public boolean more() throws JSONException {
- if(this.usePrevious) {
- return true;
- }
- try {
- this.reader.mark(1);
- } catch (IOException e) {
- throw new JSONException("Unable to preserve stream position", e);
- }
- try {
- // -1 is EOF, but next() can not consume the null character '\0'
- if(this.reader.read() <= 0) {
- this.eof = true;
- return false;
- }
- this.reader.reset();
- } catch (IOException e) {
- throw new JSONException("Unable to read the next character from the stream", e);
- }
- return true;
+ return eof && !usePrevious;
}
-
/**
* Get the next character in the source string.
*
@@ -216,85 +106,68 @@ public boolean more() throws JSONException {
*/
public char next() throws JSONException {
int c;
- if (this.usePrevious) {
- this.usePrevious = false;
- c = this.previous;
+ if (usePrevious) {
+ usePrevious = false;
+ c = previous;
} else {
try {
- c = this.reader.read();
+ c = reader.read();
} catch (IOException exception) {
throw new JSONException(exception);
}
}
if (c <= 0) { // End of stream
- this.eof = true;
+ eof = true;
return 0;
}
- this.incrementIndexes(c);
- this.previous = (char) c;
- return this.previous;
+ incrementIndexes(c);
+ previous = (char) c;
+ return previous;
}
/**
* Get the last character read from the input or '\0' if nothing has been read yet.
+ *
* @return the last character read from the input.
*/
- protected char getPrevious() { return this.previous;}
+ protected char getPrevious() {
+ return previous;
+ }
/**
* Increments the internal indexes according to the previous character
* read and the character passed as the current character.
+ *
* @param c the current character read.
*/
private void incrementIndexes(int c) {
- if(c > 0) {
- this.index++;
- if(c=='\r') {
- this.line++;
- this.characterPreviousLine = this.character;
- this.character=0;
- }else if (c=='\n') {
- if(this.previous != '\r') {
- this.line++;
- this.characterPreviousLine = this.character;
+ if (c > 0) {
+ index++;
+ if (c == '\r') {
+ line++;
+ characterPreviousLine = character;
+ character = 0;
+ } else if (c == '\n') {
+ if (previous != '\r') {
+ line++;
+ characterPreviousLine = character;
}
- this.character=0;
+ character = 0;
} else {
- this.character++;
+ character++;
}
}
}
- /**
- * Consume the next character, and check that it matches a specified
- * character.
- * @param c The character to match.
- * @return The character.
- * @throws JSONException if the character does not match.
- */
- public char next(char c) throws JSONException {
- char n = this.next();
- if (n != c) {
- if(n > 0) {
- throw this.syntaxError("Expected '" + c + "' and instead saw '" +
- n + "'");
- }
- throw this.syntaxError("Expected '" + c + "' and instead saw ''");
- }
- return n;
- }
-
-
/**
* Get the next n characters.
*
- * @param n The number of characters to take.
- * @return A string of n characters.
- * @throws JSONException
- * Substring bounds error if there are not
- * n characters remaining in the source string.
+ * @param n The number of characters to take.
+ * @return A string of n characters.
+ * @throws JSONException Substring bounds error if there are not
+ * n characters remaining in the source string.
*/
- public String next(int n) throws JSONException {
+ public String next(int n) {
if (n == 0) {
return "";
}
@@ -303,10 +176,7 @@ public String next(int n) throws JSONException {
int pos = 0;
while (pos < n) {
- chars[pos] = this.next();
- if (this.end()) {
- throw this.syntaxError("Substring bounds error");
- }
+ chars[pos] = next();
pos += 1;
}
return new String(chars);
@@ -315,12 +185,13 @@ public String next(int n) throws JSONException {
/**
* Get the next char in the string, skipping whitespace.
+ *
+ * @return A character, or 0 if there are no more characters.
* @throws JSONException Thrown if there is an error reading the source string.
- * @return A character, or 0 if there are no more characters.
*/
public char nextClean() throws JSONException {
- for (;;) {
- char c = this.next();
+ for (; ; ) {
+ char c = next();
if (c == 0 || c > ' ') {
return c;
}
@@ -333,159 +204,98 @@ public char nextClean() throws JSONException {
* Backslash processing is done. The formal JSON format does not
* allow strings in single quotes, but an implementation is allowed to
* accept them.
+ *
* @param quote The quoting character, either
- * " (double quote) or
- * ' (single quote) .
- * @return A String.
+ * " (double quote) or
+ * ' (single quote) .
+ * @return A String.
* @throws JSONException Unterminated string.
*/
public String nextString(char quote) throws JSONException {
char c;
StringBuilder sb = new StringBuilder();
- for (;;) {
- c = this.next();
+ for (; ; ) {
+ c = next();
switch (c) {
- case 0:
- case '\n':
- case '\r':
- throw this.syntaxError("Unterminated string. " +
- "Character with int code " + (int) c + " is not allowed within a quoted string.");
- case '\\':
- c = this.next();
- switch (c) {
- case 'b':
- sb.append('\b');
- break;
- case 't':
- sb.append('\t');
- break;
- case 'n':
- sb.append('\n');
- break;
- case 'f':
- sb.append('\f');
- break;
- case 'r':
- sb.append('\r');
- break;
- case 'u':
- String next = this.next(4);
- try {
- sb.append((char)Integer.parseInt(next, 16));
- } catch (NumberFormatException e) {
- throw this.syntaxError("Illegal escape. " +
- "\\u must be followed by a 4 digit hexadecimal number. \\" + next + " is not valid.", e);
- }
- break;
- case '"':
- case '\'':
+ case 0:
+ case '\n':
+ case '\r':
+ throw syntaxError("Unterminated string. " +
+ "Character with int code " + (int) c + " is not allowed within a quoted string.");
case '\\':
- case '/':
- sb.append(c);
+ c = next();
+ switch (c) {
+ case 'b':
+ sb.append('\b');
+ break;
+ case 't':
+ sb.append('\t');
+ break;
+ case 'n':
+ sb.append('\n');
+ break;
+ case 'f':
+ sb.append('\f');
+ break;
+ case 'r':
+ sb.append('\r');
+ break;
+ case 'u':
+ String next = next(4);
+ try {
+ sb.append((char) Integer.parseInt(next, 16));
+ } catch (NumberFormatException e) {
+ throw syntaxError("Illegal escape. " +
+ "\\u must be followed by a 4 digit hexadecimal number. \\" + next + " is not valid.", e);
+ }
+ break;
+ case '"':
+ case '\'':
+ case '\\':
+ case '/':
+ sb.append(c);
+ break;
+ default:
+ throw syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid.");
+ }
break;
default:
- throw this.syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid.");
- }
- break;
- default:
- if (c == quote) {
- return sb.toString();
- }
- sb.append(c);
- }
- }
- }
-
-
- /**
- * Get the text up but not including the specified character or the
- * end of line, whichever comes first.
- * @param delimiter A delimiter character.
- * @return A string.
- * @throws JSONException Thrown if there is an error while searching
- * for the delimiter
- */
- public String nextTo(char delimiter) throws JSONException {
- StringBuilder sb = new StringBuilder();
- for (;;) {
- char c = this.next();
- if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
- if (c != 0) {
- this.back();
- }
- return sb.toString().trim();
- }
- sb.append(c);
- }
- }
-
-
- /**
- * Get the text up but not including one of the specified delimiter
- * characters or the end of line, whichever comes first.
- * @param delimiters A set of delimiter characters.
- * @return A string, trimmed.
- * @throws JSONException Thrown if there is an error while searching
- * for the delimiter
- */
- public String nextTo(String delimiters) throws JSONException {
- char c;
- StringBuilder sb = new StringBuilder();
- for (;;) {
- c = this.next();
- if (delimiters.indexOf(c) >= 0 || c == 0 ||
- c == '\n' || c == '\r') {
- if (c != 0) {
- this.back();
- }
- return sb.toString().trim();
+ if (c == quote) {
+ return sb.toString();
+ }
+ sb.append(c);
}
- sb.append(c);
}
}
-
/**
* Get the next value. The value can be a Boolean, Double, Integer,
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
- * @throws JSONException If syntax error.
*
* @return An object.
+ * @throws JSONException If syntax error.
*/
public Object nextValue() throws JSONException {
- char c = this.nextClean();
- switch (c) {
- case '{':
- this.back();
- try {
- return new JSONObject(this, jsonParserConfiguration);
- } catch (StackOverflowError e) {
- throw new JSONException("JSON Array or Object depth too large to process.", e);
+ char c = nextClean();
+ return switch (c) {
+ case '{' -> {
+ back();
+ yield new JSONObject(this);
}
- case '[':
- this.back();
- try {
- return new JSONArray(this, jsonParserConfiguration);
- } catch (StackOverflowError e) {
- throw new JSONException("JSON Array or Object depth too large to process.", e);
+ case '[' -> {
+ back();
+ yield new JSONArray(this);
}
- }
- return nextSimpleValue(c);
+ default -> nextSimpleValue(c);
+ };
}
Object nextSimpleValue(char c) {
String string;
-
- // Strict mode only allows strings with explicit double quotes
- if (jsonParserConfiguration != null &&
- jsonParserConfiguration.isStrictMode() &&
- c == '\'') {
- throw this.syntaxError("Strict mode error: Single quoted strings are not allowed");
- }
switch (c) {
- case '"':
- case '\'':
- return this.nextString(c);
+ case '"':
+ case '\'':
+ return nextString(c);
}
/*
@@ -500,83 +310,38 @@ Object nextSimpleValue(char c) {
StringBuilder sb = new StringBuilder();
while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
sb.append(c);
- c = this.next();
+ c = next();
}
- if (!this.eof) {
- this.back();
+ if (!eof) {
+ back();
}
string = sb.toString().trim();
- if ("".equals(string)) {
- throw this.syntaxError("Missing value");
- }
- Object obj = JSONObject.stringToValue(string);
- // Strict mode only allows strings with explicit double quotes
- if (jsonParserConfiguration != null &&
- jsonParserConfiguration.isStrictMode() &&
- obj instanceof String) {
- throw this.syntaxError(String.format("Strict mode error: Value '%s' is not surrounded by quotes", obj));
- }
- return obj;
- }
-
-
- /**
- * Skip characters until the next character is the requested character.
- * If the requested character is not found, no characters are skipped.
- * @param to A character to skip to.
- * @return The requested character, or zero if the requested character
- * is not found.
- * @throws JSONException Thrown if there is an error while searching
- * for the to character
- */
- public char skipTo(char to) throws JSONException {
- char c;
- try {
- long startIndex = this.index;
- long startCharacter = this.character;
- long startLine = this.line;
- this.reader.mark(1000000);
- do {
- c = this.next();
- if (c == 0) {
- // in some readers, reset() may throw an exception if
- // the remaining portion of the input is greater than
- // the mark size (1,000,000 above).
- this.reader.reset();
- this.index = startIndex;
- this.character = startCharacter;
- this.line = startLine;
- return 0;
- }
- } while (c != to);
- this.reader.mark(1);
- } catch (IOException exception) {
- throw new JSONException(exception);
+ if (string.isEmpty()) {
+ throw syntaxError("Missing value");
}
- this.back();
- return c;
+ return JSONObject.stringToValue(string);
}
/**
* Make a JSONException to signal a syntax error.
*
* @param message The error message.
- * @return A JSONException object, suitable for throwing
+ * @return A JSONException object, suitable for throwing
*/
public JSONException syntaxError(String message) {
- return new JSONException(message + this.toString());
+ return new JSONException(message + this);
}
/**
* Make a JSONException to signal a syntax error.
*
- * @param message The error message.
+ * @param message The error message.
* @param causedBy The throwable that caused the error.
- * @return A JSONException object, suitable for throwing
+ * @return A JSONException object, suitable for throwing
*/
public JSONException syntaxError(String message, Throwable causedBy) {
- return new JSONException(message + this.toString(), causedBy);
+ return new JSONException(message + this, causedBy);
}
/**
@@ -586,8 +351,8 @@ public JSONException syntaxError(String message, Throwable causedBy) {
*/
@Override
public String toString() {
- return " at " + this.index + " [character " + this.character + " line " +
- this.line + "]";
+ return " at " + index + " [character " + character + " line " +
+ line + "]";
}
/**
@@ -596,7 +361,7 @@ public String toString() {
* @throws IOException If an I/O error occurs while closing the reader.
*/
public void close() throws IOException {
- if(reader!=null){
+ if (reader != null) {
reader.close();
}
}
diff --git a/src/main/java/org/json/JSONWriter.java b/src/main/java/org/json/JSONWriter.java
index 11f4a5c7e..da04d310e 100644
--- a/src/main/java/org/json/JSONWriter.java
+++ b/src/main/java/org/json/JSONWriter.java
@@ -1,6 +1,5 @@
package org.json;
-import java.io.IOException;
import java.util.Collection;
import java.util.Map;
@@ -38,245 +37,6 @@
* @version 2016-08-08
*/
public class JSONWriter {
- private static final int maxdepth = 200;
-
- /**
- * The comma flag determines if a comma should be output before the next
- * value.
- */
- private boolean comma;
-
- /**
- * The current mode. Values:
- * 'a' (array),
- * 'd' (done),
- * 'i' (initial),
- * 'k' (key),
- * 'o' (object).
- */
- protected char mode;
-
- /**
- * The object/array stack.
- */
- private final JSONObject stack[];
-
- /**
- * The stack top index. A value of 0 indicates that the stack is empty.
- */
- private int top;
-
- /**
- * The writer that will receive the output.
- */
- protected Appendable writer;
-
- /**
- * Make a fresh JSONWriter. It can be used to build one JSON text.
- * @param w an appendable object
- */
- public JSONWriter(Appendable w) {
- this.comma = false;
- this.mode = 'i';
- this.stack = new JSONObject[maxdepth];
- this.top = 0;
- this.writer = w;
- }
-
- /**
- * Append a value.
- * @param string A string value.
- * @return this
- * @throws JSONException If the value is out of sequence.
- */
- private JSONWriter append(String string) throws JSONException {
- if (string == null) {
- throw new JSONException("Null pointer");
- }
- if (this.mode == 'o' || this.mode == 'a') {
- try {
- if (this.comma && this.mode == 'a') {
- this.writer.append(',');
- }
- this.writer.append(string);
- } catch (IOException e) {
- // Android as of API 25 does not support this exception constructor
- // however we won't worry about it. If an exception is happening here
- // it will just throw a "Method not found" exception instead.
- throw new JSONException(e);
- }
- if (this.mode == 'o') {
- this.mode = 'k';
- }
- this.comma = true;
- return this;
- }
- throw new JSONException("Value out of sequence.");
- }
-
- /**
- * Begin appending a new array. All values until the balancing
- * endArray will be appended to this array. The
- * endArray method must be called to mark the array's end.
- * @return this
- * @throws JSONException If the nesting is too deep, or if the object is
- * started in the wrong place (for example as a key or after the end of the
- * outermost array or object).
- */
- public JSONWriter array() throws JSONException {
- if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
- this.push(null);
- this.append("[");
- this.comma = false;
- return this;
- }
- throw new JSONException("Misplaced array.");
- }
-
- /**
- * End something.
- * @param m Mode
- * @param c Closing character
- * @return this
- * @throws JSONException If unbalanced.
- */
- private JSONWriter end(char m, char c) throws JSONException {
- if (this.mode != m) {
- throw new JSONException(m == 'a'
- ? "Misplaced endArray."
- : "Misplaced endObject.");
- }
- this.pop(m);
- try {
- this.writer.append(c);
- } catch (IOException e) {
- // Android as of API 25 does not support this exception constructor
- // however we won't worry about it. If an exception is happening here
- // it will just throw a "Method not found" exception instead.
- throw new JSONException(e);
- }
- this.comma = true;
- return this;
- }
-
- /**
- * End an array. This method most be called to balance calls to
- * array.
- * @return this
- * @throws JSONException If incorrectly nested.
- */
- public JSONWriter endArray() throws JSONException {
- return this.end('a', ']');
- }
-
- /**
- * End an object. This method most be called to balance calls to
- * object.
- * @return this
- * @throws JSONException If incorrectly nested.
- */
- public JSONWriter endObject() throws JSONException {
- return this.end('k', '}');
- }
-
- /**
- * Append a key. The key will be associated with the next value. In an
- * object, every value must be preceded by a key.
- * @param string A key string.
- * @return this
- * @throws JSONException If the key is out of place. For example, keys
- * do not belong in arrays or if the key is null.
- */
- public JSONWriter key(String string) throws JSONException {
- if (string == null) {
- throw new JSONException("Null key.");
- }
- if (this.mode == 'k') {
- try {
- JSONObject topObject = this.stack[this.top - 1];
- // don't use the built in putOnce method to maintain Android support
- if(topObject.has(string)) {
- throw new JSONException("Duplicate key \"" + string + "\"");
- }
- topObject.put(string, true);
- if (this.comma) {
- this.writer.append(',');
- }
- this.writer.append(JSONObject.quote(string));
- this.writer.append(':');
- this.comma = false;
- this.mode = 'o';
- return this;
- } catch (IOException e) {
- // Android as of API 25 does not support this exception constructor
- // however we won't worry about it. If an exception is happening here
- // it will just throw a "Method not found" exception instead.
- throw new JSONException(e);
- }
- }
- throw new JSONException("Misplaced key.");
- }
-
-
- /**
- * Begin appending a new object. All keys and values until the balancing
- * endObject will be appended to this object. The
- * endObject method must be called to mark the object's end.
- * @return this
- * @throws JSONException If the nesting is too deep, or if the object is
- * started in the wrong place (for example as a key or after the end of the
- * outermost array or object).
- */
- public JSONWriter object() throws JSONException {
- if (this.mode == 'i') {
- this.mode = 'o';
- }
- if (this.mode == 'o' || this.mode == 'a') {
- this.append("{");
- this.push(new JSONObject());
- this.comma = false;
- return this;
- }
- throw new JSONException("Misplaced object.");
-
- }
-
-
- /**
- * Pop an array or object scope.
- * @param c The scope to close.
- * @throws JSONException If nesting is wrong.
- */
- private void pop(char c) throws JSONException {
- if (this.top <= 0) {
- throw new JSONException("Nesting error.");
- }
- char m = this.stack[this.top - 1] == null ? 'a' : 'k';
- if (m != c) {
- throw new JSONException("Nesting error.");
- }
- this.top -= 1;
- this.mode = this.top == 0
- ? 'd'
- : this.stack[this.top - 1] == null
- ? 'a'
- : 'k';
- }
-
- /**
- * Push an array or object scope.
- * @param jo The scope to open.
- * @throws JSONException If nesting is too deep.
- */
- private void push(JSONObject jo) throws JSONException {
- if (this.top >= maxdepth) {
- throw new JSONException("Nesting too deep.");
- }
- this.stack[this.top] = jo;
- this.mode = jo == null ? 'a' : 'k';
- this.top += 1;
- }
-
/**
* Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce the
@@ -302,7 +62,7 @@ private void push(JSONObject jo) throws JSONException {
* If the value is or contains an invalid number.
*/
public static String valueToString(Object value) throws JSONException {
- if (value == null || value.equals(null)) {
+ if (value == null) {
return "null";
}
if (value instanceof JSONString) {
@@ -315,7 +75,7 @@ public static String valueToString(Object value) throws JSONException {
if (object != null) {
return object;
}
- throw new JSONException("Bad value from toJSONString: " + object);
+ throw new JSONException("error value");
}
if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
@@ -332,12 +92,10 @@ public static String valueToString(Object value) throws JSONException {
|| value instanceof JSONArray) {
return value.toString();
}
- if (value instanceof Map) {
- Map, ?> map = (Map, ?>) value;
+ if (value instanceof Map, ?> map) {
return new JSONObject(map).toString();
}
- if (value instanceof Collection) {
- Collection> coll = (Collection>) value;
+ if (value instanceof Collection> coll) {
return new JSONArray(coll).toString();
}
if (value.getClass().isArray()) {
@@ -348,47 +106,4 @@ public static String valueToString(Object value) throws JSONException {
}
return JSONObject.quote(value.toString());
}
-
- /**
- * Append either the value true or the value
- * false.
- * @param b A boolean.
- * @return this
- * @throws JSONException if a called function has an error
- */
- public JSONWriter value(boolean b) throws JSONException {
- return this.append(b ? "true" : "false");
- }
-
- /**
- * Append a double value.
- * @param d A double.
- * @return this
- * @throws JSONException If the number is not finite.
- */
- public JSONWriter value(double d) throws JSONException {
- return this.value(Double.valueOf(d));
- }
-
- /**
- * Append a long value.
- * @param l A long.
- * @return this
- * @throws JSONException if a called function has an error
- */
- public JSONWriter value(long l) throws JSONException {
- return this.append(Long.toString(l));
- }
-
-
- /**
- * Append an object value.
- * @param object The object to append. It can be null, or a Boolean, Number,
- * String, JSONObject, or JSONArray, or an object that implements JSONString.
- * @return this
- * @throws JSONException If the value is out of sequence.
- */
- public JSONWriter value(Object object) throws JSONException {
- return this.append(valueToString(object));
- }
}
diff --git a/src/main/java/org/json/ParserConfiguration.java b/src/main/java/org/json/ParserConfiguration.java
deleted file mode 100644
index 06cc44366..000000000
--- a/src/main/java/org/json/ParserConfiguration.java
+++ /dev/null
@@ -1,126 +0,0 @@
-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 (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string).
- */
- protected boolean keepStrings;
-
- /**
- * The maximum nesting depth when parsing an object.
- */
- protected int maxNestingDepth;
-
- /**
- * Constructs a new ParserConfiguration with default settings.
- */
- public ParserConfiguration() {
- this.keepStrings = false;
- this.maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
- }
-
- /**
- * Constructs a new ParserConfiguration with the specified settings.
- *
- * @param keepStrings A boolean indicating whether to preserve strings during parsing.
- * @param maxNestingDepth An integer representing the maximum allowed 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 (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string).
- *
- * @return The keepStrings configuration value.
- */
- public boolean isKeepStrings() {
- return this.keepStrings;
- }
-
- /**
- * When parsing the XML into JSONML, specifies if values should be kept as strings (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string)
- *
- * @param newVal new value to use for the keepStrings configuration option.
- * @param the type of the configuration object
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- @SuppressWarnings("unchecked")
- public 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 an object (e.g. Map, Collection) into JSON-related objects.
- *
- * @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 an object (e.g. Map, Collection) into JSON-related objects.
- * 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
- * @param the type of the configuration object
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- @SuppressWarnings("unchecked")
- public 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;
- }
-}
diff --git a/src/main/java/org/json/Property.java b/src/main/java/org/json/Property.java
deleted file mode 100644
index ba6c56967..000000000
--- a/src/main/java/org/json/Property.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.json;
-
-/*
-Public Domain.
-*/
-
-import java.util.Enumeration;
-import java.util.Properties;
-
-/**
- * Converts a Property file data into JSONObject and back.
- * @author JSON.org
- * @version 2015-05-05
- */
-public class Property {
-
- /**
- * Constructs a new Property object.
- */
- public Property() {
- }
-
- /**
- * Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
- * @param properties java.util.Properties
- * @return JSONObject
- * @throws JSONException if a called function has an error
- */
- public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
- // can't use the new constructor for Android support
- // JSONObject jo = new JSONObject(properties == null ? 0 : properties.size());
- JSONObject jo = new JSONObject();
- if (properties != null && !properties.isEmpty()) {
- Enumeration> enumProperties = properties.propertyNames();
- while(enumProperties.hasMoreElements()) {
- String name = (String)enumProperties.nextElement();
- jo.put(name, properties.getProperty(name));
- }
- }
- return jo;
- }
-
- /**
- * Converts the JSONObject into a property file object.
- * @param jo JSONObject
- * @return java.util.Properties
- * @throws JSONException if a called function has an error
- */
- public static Properties toProperties(JSONObject jo) throws JSONException {
- Properties properties = new Properties();
- if (jo != null) {
- // Don't use the new entrySet API to maintain Android support
- for (final String key : jo.keySet()) {
- Object value = jo.opt(key);
- if (!JSONObject.NULL.equals(value)) {
- properties.put(key, value.toString());
- }
- }
- }
- return properties;
- }
-}
diff --git a/src/main/java/org/json/StringBuilderWriter.java b/src/main/java/org/json/StringBuilderWriter.java
index 4aaa4903f..4c22f16ae 100644
--- a/src/main/java/org/json/StringBuilderWriter.java
+++ b/src/main/java/org/json/StringBuilderWriter.java
@@ -1,6 +1,5 @@
package org.json;
-import java.io.IOException;
import java.io.Writer;
/**
@@ -87,6 +86,6 @@ public void flush() {
}
@Override
- public void close() throws IOException {
+ public void close() {
}
}
diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java
deleted file mode 100644
index 4bf475935..000000000
--- a/src/main/java/org/json/XML.java
+++ /dev/null
@@ -1,1132 +0,0 @@
-package org.json;
-
-/*
-Public Domain.
-*/
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Iterator;
-
-/**
- * This provides static methods to convert an XML text into a JSONObject, and to
- * covert a JSONObject into an XML text.
- *
- * @author JSON.org
- * @version 2016-08-10
- */
-@SuppressWarnings("boxing")
-public class XML {
-
- /**
- * Constructs a new XML object.
- */
- public XML() {
- }
-
- /** The Character '&'. */
- public static final Character AMP = '&';
-
- /** The Character '''. */
- public static final Character APOS = '\'';
-
- /** The Character '!'. */
- public static final Character BANG = '!';
-
- /** The Character '='. */
- public static final Character EQ = '=';
-
- /** The Character {@code '>'. } */
- public static final Character GT = '>';
-
- /** The Character '<'. */
- public static final Character LT = '<';
-
- /** The Character '?'. */
- public static final Character QUEST = '?';
-
- /** The Character '"'. */
- public static final Character QUOT = '"';
-
- /** The Character '/'. */
- public static final Character SLASH = '/';
-
- /**
- * Null attribute name
- */
- public static final String NULL_ATTR = "xsi:nil";
-
- /**
- * Represents the XML attribute name for specifying type information.
- */
- public static final String TYPE_ATTR = "xsi:type";
-
- /**
- * Creates an iterator for navigating Code Points in a string instead of
- * characters. Once Java7 support is dropped, this can be replaced with
- *
- * string.codePoints()
- *
- * which is available in Java8 and above.
- *
- * @see http://stackoverflow.com/a/21791059/6030888
- */
- private static Iterable codePointIterator(final String string) {
- return new Iterable() {
- @Override
- public Iterator iterator() {
- return new Iterator() {
- private int nextIndex = 0;
- private int length = string.length();
-
- @Override
- public boolean hasNext() {
- return this.nextIndex < this.length;
- }
-
- @Override
- public Integer next() {
- int result = string.codePointAt(this.nextIndex);
- this.nextIndex += Character.charCount(result);
- return result;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
- };
- }
-
- /**
- * Replace special characters with XML escapes:
- *
- * {@code
- * & (ampersand) is replaced by &
- * < (less than) is replaced by <
- * > (greater than) is replaced by >
- * " (double quote) is replaced by "
- * ' (single quote / apostrophe) is replaced by '
- * }
- *
- * @param string
- * The string to be escaped.
- * @return The escaped string.
- */
- public static String escape(String string) {
- StringBuilder sb = new StringBuilder(string.length());
- for (final int cp : codePointIterator(string)) {
- switch (cp) {
- case '&':
- sb.append("&");
- break;
- case '<':
- sb.append("<");
- break;
- case '>':
- sb.append(">");
- break;
- case '"':
- sb.append(""");
- break;
- case '\'':
- sb.append("'");
- break;
- default:
- if (mustEscape(cp)) {
- sb.append("");
- sb.append(Integer.toHexString(cp));
- sb.append(';');
- } else {
- sb.appendCodePoint(cp);
- }
- }
- }
- return sb.toString();
- }
-
- /**
- * @param cp code point to test
- * @return true if the code point is not valid for an XML
- */
- private static boolean mustEscape(int cp) {
- /* Valid range from https://www.w3.org/TR/REC-xml/#charsets
- *
- * #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
- *
- * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
- */
- // isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
- // all ISO control characters are out of range except tabs and new lines
- return (Character.isISOControl(cp)
- && cp != 0x9
- && cp != 0xA
- && cp != 0xD
- ) || !(
- // valid the range of acceptable characters that aren't control
- (cp >= 0x20 && cp <= 0xD7FF)
- || (cp >= 0xE000 && cp <= 0xFFFD)
- || (cp >= 0x10000 && cp <= 0x10FFFF)
- )
- ;
- }
-
- /**
- * Removes XML escapes from the string.
- *
- * @param string
- * string to remove escapes from
- * @return string with converted entities
- */
- public static String unescape(String string) {
- StringBuilder sb = new StringBuilder(string.length());
- for (int i = 0, length = string.length(); i < length; i++) {
- char c = string.charAt(i);
- if (c == '&') {
- final int semic = string.indexOf(';', i);
- if (semic > i) {
- final String entity = string.substring(i + 1, semic);
- sb.append(XMLTokener.unescapeEntity(entity));
- // skip past the entity we just parsed.
- i += entity.length() + 1;
- } else {
- // this shouldn't happen in most cases since the parser
- // errors on unclosed entries.
- sb.append(c);
- }
- } else {
- // not part of an entity
- sb.append(c);
- }
- }
- return sb.toString();
- }
-
- /**
- * Throw an exception if the string contains whitespace. Whitespace is not
- * allowed in tagNames and attributes.
- *
- * @param string
- * A string.
- * @throws JSONException Thrown if the string contains whitespace or is empty.
- */
- public static void noSpace(String string) throws JSONException {
- int i, length = string.length();
- if (length == 0) {
- throw new JSONException("Empty string.");
- }
- for (i = 0; i < length; i += 1) {
- if (Character.isWhitespace(string.charAt(i))) {
- throw new JSONException("'" + string
- + "' contains a space character.");
- }
- }
- }
-
- /**
- * Scan the content following the named tag, attaching it to the context.
- *
- * @param x
- * The XMLTokener containing the source string.
- * @param context
- * 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 Thrown if any parsing error occurs.
- */
- private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, int currentNestingDepth)
- throws JSONException {
- char c;
- int i;
- JSONObject jsonObject = null;
- String string;
- String tagName;
- Object token;
- XMLXsiTypeConverter> xmlXsiTypeConverter;
-
- // Test for and skip past these forms:
- //
- //
- //
- // ... ?>
- // Report errors for these forms:
- // <>
- // <=
- // <<
-
- token = x.nextToken();
-
- // ");
- return false;
- }
- x.back();
- } else if (c == '[') {
- token = x.nextToken();
- if ("CDATA".equals(token)) {
- if (x.next() == '[') {
- string = x.nextCDATA();
- if (string.length() > 0) {
- context.accumulate(config.getcDataTagName(), string);
- }
- return false;
- }
- }
- throw x.syntaxError("Expected 'CDATA['");
- }
- i = 1;
- do {
- token = x.nextMeta();
- if (token == null) {
- throw x.syntaxError("Missing '>' after ' 0);
- return false;
- } else if (token == QUEST) {
-
- //
- x.skipPast("?>");
- return false;
- } else if (token == SLASH) {
-
- // Close tag
-
- token = x.nextToken();
- if (name == null) {
- throw x.syntaxError("Mismatched close tag " + token);
- }
- if (!token.equals(name)) {
- throw x.syntaxError("Mismatched " + name + " and " + token);
- }
- if (x.nextToken() != GT) {
- throw x.syntaxError("Misshaped close tag");
- }
- return true;
-
- } else if (token instanceof Character) {
- throw x.syntaxError("Misshaped tag");
-
- // Open tag <
-
- } else {
- tagName = (String) token;
- token = null;
- jsonObject = new JSONObject();
- boolean nilAttributeFound = false;
- xmlXsiTypeConverter = null;
- for (;;) {
- if (token == null) {
- token = x.nextToken();
- }
- // attribute = value
- if (token instanceof String) {
- string = (String) token;
- token = x.nextToken();
- if (token == EQ) {
- token = x.nextToken();
- if (!(token instanceof String)) {
- throw x.syntaxError("Missing value");
- }
-
- if (config.isConvertNilAttributeToNull()
- && NULL_ATTR.equals(string)
- && Boolean.parseBoolean((String) token)) {
- nilAttributeFound = true;
- } else if(config.getXsiTypeMap() != null && !config.getXsiTypeMap().isEmpty()
- && TYPE_ATTR.equals(string)) {
- xmlXsiTypeConverter = config.getXsiTypeMap().get(token);
- } else if (!nilAttributeFound) {
- Object obj = stringToValue((String) token);
- if (obj instanceof Boolean) {
- jsonObject.accumulate(string,
- config.isKeepBooleanAsString()
- ? ((String) token)
- : obj);
- } else if (obj instanceof Number) {
- jsonObject.accumulate(string,
- config.isKeepNumberAsString()
- ? ((String) token)
- : obj);
- } else {
- jsonObject.accumulate(string, stringToValue((String) token));
- }
- }
- token = null;
- } else {
- jsonObject.accumulate(string, "");
- }
-
-
- } else if (token == SLASH) {
- // Empty tag <.../>
- if (x.nextToken() != GT) {
- throw x.syntaxError("Misshaped tag");
- }
- if (config.getForceList().contains(tagName)) {
- // Force the value to be an array
- if (nilAttributeFound) {
- context.append(tagName, JSONObject.NULL);
- } else if (jsonObject.length() > 0) {
- context.append(tagName, jsonObject);
- } else {
- context.put(tagName, new JSONArray());
- }
- } else {
- if (nilAttributeFound) {
- context.accumulate(tagName, JSONObject.NULL);
- } else if (jsonObject.length() > 0) {
- context.accumulate(tagName, jsonObject);
- } else {
- context.accumulate(tagName, "");
- }
- }
- return false;
-
- } else if (token == GT) {
- // Content, between <...> and
- for (;;) {
- token = x.nextContent();
- if (token == null) {
- if (tagName != null) {
- throw x.syntaxError("Unclosed tag " + tagName);
- }
- return false;
- } else if (token instanceof String) {
- string = (String) token;
- if (string.length() > 0) {
- if(xmlXsiTypeConverter != null) {
- jsonObject.accumulate(config.getcDataTagName(),
- stringToValue(string, xmlXsiTypeConverter));
- } else {
- Object obj = stringToValue((String) token);
- if (obj instanceof Boolean) {
- jsonObject.accumulate(config.getcDataTagName(),
- config.isKeepBooleanAsString()
- ? ((String) token)
- : obj);
- } else if (obj instanceof Number) {
- jsonObject.accumulate(config.getcDataTagName(),
- config.isKeepNumberAsString()
- ? ((String) token)
- : obj);
- } else {
- jsonObject.accumulate(config.getcDataTagName(), stringToValue((String) token));
- }
- }
- }
-
- } else if (token == LT) {
- // Nested element
- 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) {
- context.put(tagName, new JSONArray());
- } else if (jsonObject.length() == 1
- && jsonObject.opt(config.getcDataTagName()) != null) {
- context.append(tagName, jsonObject.opt(config.getcDataTagName()));
- } else {
- context.append(tagName, jsonObject);
- }
- } else {
- if (jsonObject.length() == 0) {
- context.accumulate(tagName, "");
- } else if (jsonObject.length() == 1
- && jsonObject.opt(config.getcDataTagName()) != null) {
- context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
- } else {
- if (!config.shouldTrimWhiteSpace()) {
- removeEmpty(jsonObject, config);
- }
- context.accumulate(tagName, jsonObject);
- }
- }
-
- return false;
- }
- }
- }
- } else {
- throw x.syntaxError("Misshaped tag");
- }
- }
- }
- }
- /**
- * This method removes any JSON entry which has the key set by XMLParserConfiguration.cDataTagName
- * and contains whitespace as this is caused by whitespace between tags. See test XMLTest.testNestedWithWhitespaceTrimmingDisabled.
- * @param jsonObject JSONObject which may require deletion
- * @param config The XMLParserConfiguration which includes the cDataTagName
- */
- private static void removeEmpty(final JSONObject jsonObject, final XMLParserConfiguration config) {
- if (jsonObject.has(config.getcDataTagName())) {
- final Object s = jsonObject.get(config.getcDataTagName());
- if (s instanceof String) {
- if (isStringAllWhiteSpace(s.toString())) {
- jsonObject.remove(config.getcDataTagName());
- }
- }
- else if (s instanceof JSONArray) {
- final JSONArray sArray = (JSONArray) s;
- for (int k = sArray.length()-1; k >= 0; k--){
- final Object eachString = sArray.get(k);
- if (eachString instanceof String) {
- String s1 = (String) eachString;
- if (isStringAllWhiteSpace(s1)) {
- sArray.remove(k);
- }
- }
- }
- if (sArray.isEmpty()) {
- jsonObject.remove(config.getcDataTagName());
- }
- }
- }
- }
-
- private static boolean isStringAllWhiteSpace(final String s) {
- for (int k = 0; k= '0' && initial <= '9') || initial == '-') {
- // decimal representation
- if (isDecimalNotation(val)) {
- // Use a BigDecimal all the time so we keep the original
- // representation. BigDecimal doesn't support -0.0, ensure we
- // keep that by forcing a decimal.
- try {
- BigDecimal bd = new BigDecimal(val);
- if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) {
- return Double.valueOf(-0.0);
- }
- return bd;
- } catch (NumberFormatException retryAsDouble) {
- // this is to support "Hex Floats" like this: 0x1.0P-1074
- try {
- Double d = Double.valueOf(val);
- if(d.isNaN() || d.isInfinite()) {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
- }
- return d;
- } catch (NumberFormatException ignore) {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
- }
- }
- }
- // block items like 00 01 etc. Java number parsers treat these as Octal.
- if(initial == '0' && val.length() > 1) {
- char at1 = val.charAt(1);
- if(at1 >= '0' && at1 <= '9') {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
- }
- } else if (initial == '-' && val.length() > 2) {
- char at1 = val.charAt(1);
- char at2 = val.charAt(2);
- if(at1 == '0' && at2 >= '0' && at2 <= '9') {
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
- }
- }
- // 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
- // long lived.
- BigInteger bi = new BigInteger(val);
- if(bi.bitLength() <= 31){
- return Integer.valueOf(bi.intValue());
- }
- if(bi.bitLength() <= 63){
- return Long.valueOf(bi.longValue());
- }
- return bi;
- }
- throw new NumberFormatException("val ["+val+"] is not a valid number.");
- }
-
- /**
- * direct copy of {@link JSONObject#isDecimalNotation(String)} to maintain Android support.
- */
- private static boolean isDecimalNotation(final String val) {
- return val.indexOf('.') > -1 || val.indexOf('e') > -1
- || val.indexOf('E') > -1 || "-0".equals(val);
- }
-
- /**
- * This method tries to convert the given string value to the target object
- * @param string String to convert
- * @param typeConverter value converter to convert string to integer, boolean e.t.c
- * @return JSON value of this string or the string
- */
- public static Object stringToValue(String string, XMLXsiTypeConverter> typeConverter) {
- if(typeConverter != null) {
- return typeConverter.convert(string);
- }
- return stringToValue(string);
- }
-
- /**
- * This method is the same as {@link JSONObject#stringToValue(String)}.
- *
- * @param string String to convert
- * @return JSON value of this string or the string
- */
- // To maintain compatibility with the Android API, this method is a direct copy of
- // the one in JSONObject. Changes made here should be reflected there.
- // This method should not make calls out of the XML object.
- public static Object stringToValue(String string) {
- if ("".equals(string)) {
- return string;
- }
-
- // check JSON key words true/false/null
- if ("true".equalsIgnoreCase(string)) {
- return Boolean.TRUE;
- }
- if ("false".equalsIgnoreCase(string)) {
- return Boolean.FALSE;
- }
- if ("null".equalsIgnoreCase(string)) {
- return JSONObject.NULL;
- }
-
- /*
- * If it might be a number, try converting it. If a number cannot be
- * produced, then the value will just be a string.
- */
-
- char initial = string.charAt(0);
- if ((initial >= '0' && initial <= '9') || initial == '-') {
- try {
- return stringToNumber(string);
- } catch (Exception ignore) {
- }
- }
- return string;
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * @param string
- * The source string.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string) throws JSONException {
- return toJSONObject(string, XMLParserConfiguration.ORIGINAL);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * @param reader The XML source reader.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(Reader reader) throws JSONException {
- return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param reader The XML source reader.
- * @param keepStrings If true, then 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 if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
- if(keepStrings) {
- return toJSONObject(reader, XMLParserConfiguration.KEEP_STRINGS);
- }
- return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All numbers are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document depending
- * on how flag is set.
- * All booleans are converted as strings, for true, false will not be coerced to
- * booleans but will instead be the exact value as seen in the XML document depending
- * on how flag is set.
- *
- * @param reader The XML source reader.
- * @param keepNumberAsString If true, then numeric values will not be coerced into
- * numeric values and will instead be left as strings
- * @param keepBooleanAsString If true, then boolean values will not be coerced into
- * * numeric values and will instead be left as strings
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(Reader reader, boolean keepNumberAsString, boolean keepBooleanAsString) throws JSONException {
- XMLParserConfiguration xmlParserConfiguration = new XMLParserConfiguration();
- if(keepNumberAsString) {
- xmlParserConfiguration = xmlParserConfiguration.withKeepNumberAsString(keepNumberAsString);
- }
- if(keepBooleanAsString) {
- xmlParserConfiguration = xmlParserConfiguration.withKeepBooleanAsString(keepBooleanAsString);
- }
- return toJSONObject(reader, xmlParserConfiguration);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param reader The XML source reader.
- * @param config Configuration options for the parser
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(Reader reader, XMLParserConfiguration config) throws JSONException {
- JSONObject jo = new JSONObject();
- XMLTokener x = new XMLTokener(reader, config);
- while (x.more()) {
- x.skipPast("<");
- if(x.more()) {
- parse(x, jo, null, config, 0);
- }
- }
- return jo;
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param string
- * The source string.
- * @param keepStrings If true, then 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 if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
- return toJSONObject(new StringReader(string), keepStrings);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All numbers are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document depending
- * on how flag is set.
- * All booleans are converted as strings, for true, false will not be coerced to
- * booleans but will instead be the exact value as seen in the XML document depending
- * on how flag is set.
- *
- * @param string
- * The source string.
- * @param keepNumberAsString If true, then numeric values will not be coerced into
- * numeric values and will instead be left as strings
- * @param keepBooleanAsString If true, then boolean values will not be coerced into
- * numeric values and will instead be left as strings
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string, boolean keepNumberAsString, boolean keepBooleanAsString) throws JSONException {
- return toJSONObject(new StringReader(string), keepNumberAsString, keepBooleanAsString);
- }
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject. Some information may be lost in this transformation because
- * JSON is a data format and XML is a document format. XML uses elements,
- * attributes, and content text, while JSON uses unordered collections of
- * 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 {@code
- * <[ [ ]]>}
- * are ignored.
- *
- * All values are converted as strings, for 1, 01, 29.0 will not be coerced to
- * numbers but will instead be the exact value as seen in the XML document.
- *
- * @param string
- * The source string.
- * @param config Configuration options for the parser.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException Thrown if there is an errors while parsing the string
- */
- public static JSONObject toJSONObject(String string, XMLParserConfiguration config) throws JSONException {
- return toJSONObject(new StringReader(string), config);
- }
-
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(Object object) throws JSONException {
- return toString(object, null, XMLParserConfiguration.ORIGINAL);
- }
-
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(final Object object, final String tagName) {
- return toString(object, tagName, XMLParserConfiguration.ORIGINAL);
- }
-
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @param config
- * Configuration that can control output to XML.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(final Object object, final String tagName, final XMLParserConfiguration config)
- throws JSONException {
- return toString(object, tagName, config, 0, 0);
- }
-
- /**
- * Convert a JSONObject into a well-formed, element-normal XML string,
- * either pretty print or single-lined depending on indent factor.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @param config
- * Configuration that can control output to XML.
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
- * @param indent
- * The current ident level in spaces.
- * @return
- * @throws JSONException
- */
- private static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor, int indent)
- throws JSONException {
- StringBuilder sb = new StringBuilder();
- JSONArray ja;
- JSONObject jo;
- String string;
-
- if (object instanceof JSONObject) {
-
- // Emit
- if (tagName != null) {
- sb.append(indent(indent));
- sb.append('<');
- sb.append(tagName);
- sb.append('>');
- if(indentFactor > 0){
- sb.append("\n");
- indent += indentFactor;
- }
- }
-
- // Loop thru the keys.
- // don't use the new entrySet accessor to maintain Android Support
- jo = (JSONObject) object;
- for (final String key : jo.keySet()) {
- Object value = jo.opt(key);
- if (value == null) {
- value = "";
- } else if (value.getClass().isArray()) {
- value = new JSONArray(value);
- }
-
- // Emit content in body
- if (key.equals(config.getcDataTagName())) {
- if (value instanceof JSONArray) {
- ja = (JSONArray) value;
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- if (i > 0) {
- sb.append('\n');
- }
- Object val = ja.opt(i);
- sb.append(escape(val.toString()));
- }
- } else {
- sb.append(escape(value.toString()));
- }
-
- // Emit an array of similar keys
-
- } else if (value instanceof JSONArray) {
- ja = (JSONArray) value;
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- Object val = ja.opt(i);
- if (val instanceof JSONArray) {
- sb.append('<');
- sb.append(key);
- sb.append('>');
- sb.append(toString(val, null, config, indentFactor, indent));
- sb.append("");
- sb.append(key);
- sb.append('>');
- } else {
- sb.append(toString(val, key, config, indentFactor, indent));
- }
- }
- } else if ("".equals(value)) {
- if (config.isCloseEmptyTag()){
- sb.append(indent(indent));
- sb.append('<');
- sb.append(key);
- sb.append(">");
- sb.append("");
- sb.append(key);
- sb.append(">");
- if (indentFactor > 0) {
- sb.append("\n");
- }
- }else {
- sb.append(indent(indent));
- sb.append('<');
- sb.append(key);
- sb.append("/>");
- if (indentFactor > 0) {
- sb.append("\n");
- }
- }
-
- // Emit a new tag
-
- } else {
- sb.append(toString(value, key, config, indentFactor, indent));
- }
- }
- if (tagName != null) {
-
- // Emit the close tag
- sb.append(indent(indent - indentFactor));
- sb.append("");
- sb.append(tagName);
- sb.append('>');
- if(indentFactor > 0){
- sb.append("\n");
- }
- }
- return sb.toString();
-
- }
-
- if (object != null && (object instanceof JSONArray || object.getClass().isArray())) {
- if(object.getClass().isArray()) {
- ja = new JSONArray(object);
- } else {
- ja = (JSONArray) object;
- }
- int jaLength = ja.length();
- // don't use the new iterator API to maintain support for Android
- for (int i = 0; i < jaLength; i++) {
- Object val = ja.opt(i);
- // XML does not have good support for arrays. If an array
- // appears in a place where XML is lacking, synthesize an
- // element.
- sb.append(toString(val, tagName == null ? "array" : tagName, config, indentFactor, indent));
- }
- return sb.toString();
- }
-
-
- string = (object == null) ? "null" : escape(object.toString());
- String indentationSuffix = (indentFactor > 0) ? "\n" : "";
- if(tagName == null){
- return indent(indent) + "\"" + string + "\"" + indentationSuffix;
- } else if(string.length() == 0){
- return indent(indent) + "<" + tagName + "/>" + indentationSuffix;
- } else {
- return indent(indent) + "<" + tagName
- + ">" + string + "" + tagName + ">" + indentationSuffix;
- }
- }
-
- /**
- * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(Object object, int indentFactor){
- return toString(object, null, XMLParserConfiguration.ORIGINAL, indentFactor);
- }
-
- /**
- * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(final Object object, final String tagName, int indentFactor) {
- return toString(object, tagName, XMLParserConfiguration.ORIGINAL, indentFactor);
- }
-
- /**
- * Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
- *
- * @param object
- * A JSONObject.
- * @param tagName
- * The optional name of the enclosing tag.
- * @param config
- * Configuration that can control output to XML.
- * @param indentFactor
- * The number of spaces to add to each level of indentation.
- * @return A string.
- * @throws JSONException Thrown if there is an error parsing the string
- */
- public static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor)
- throws JSONException {
- return toString(object, tagName, config, indentFactor, 0);
- }
-
- /**
- * Return a String consisting of a number of space characters specified by indent
- *
- * @param indent
- * The number of spaces to be appended to the String.
- * @return
- */
- private static final String indent(int indent) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < indent; i++) {
- sb.append(' ');
- }
- return sb.toString();
- }
-}
diff --git a/src/main/java/org/json/XMLParserConfiguration.java b/src/main/java/org/json/XMLParserConfiguration.java
deleted file mode 100644
index de84b90cb..000000000
--- a/src/main/java/org/json/XMLParserConfiguration.java
+++ /dev/null
@@ -1,444 +0,0 @@
-package org.json;
-/*
-Public Domain.
-*/
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * Configuration object for the XML parser. The configuration is immutable.
- * @author AylwardJ
- */
-@SuppressWarnings({""})
-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
-
- /**
- * Allow user to control how numbers are parsed
- */
- private boolean keepNumberAsString;
-
- /**
- * Allow user to control how booleans are parsed
- */
- private boolean keepBooleanAsString;
-
- /** Original Configuration of the XML Parser. */
- public static final XMLParserConfiguration ORIGINAL
- = new XMLParserConfiguration();
- /** Original configuration of the XML Parser except that values are kept as strings. */
- public static final XMLParserConfiguration KEEP_STRINGS
- = new XMLParserConfiguration().withKeepStrings(true);
-
- /**
- * 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 null 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(false), or they should be converted to
- * null(true)
- */
- private boolean convertNilAttributeToNull;
-
- /**
- * When creating an XML from JSON Object, an empty tag by default will self-close.
- * If it has to be closed explicitly, with empty content between start and end tag,
- * this flag is to be turned on.
- */
- private boolean closeEmptyTag;
-
- /**
- * This will allow type conversion for values in XML if xsi:type attribute is defined
- */
- private Map> xsiTypeMap;
-
- /**
- * When parsing the XML into JSON, specifies the tags whose values should be converted
- * to arrays
- */
- private Set forceList;
-
-
- /**
- * Flag to indicate whether white space should be trimmed when parsing XML.
- * The default behaviour is to trim white space. When this is set to false, inputting XML
- * with tags that are the same as the value of cDataTagName is unsupported. It is recommended to set cDataTagName
- * to a distinct value in this case.
- */
- private boolean shouldTrimWhiteSpace;
-
- /**
- * Default parser configuration. Does not keep strings (tries to implicitly convert
- * values), and the CDATA Tag Name is "content". Trims whitespace.
- */
- public XMLParserConfiguration () {
- super();
- this.cDataTagName = "content";
- this.convertNilAttributeToNull = false;
- this.xsiTypeMap = Collections.emptyMap();
- this.forceList = Collections.emptySet();
- this.shouldTrimWhiteSpace = true;
- }
-
- /**
- * Configure the parser string processing and use the default CDATA Tag Name as "content".
- * @param keepStrings true to parse all values as string.
- * false to try and convert XML string values into a JSON value.
- * @deprecated This constructor has been deprecated in favor of using the new builder
- * pattern for the configuration.
- * This constructor may be removed in a future release.
- */
- @Deprecated
- public XMLParserConfiguration (final boolean keepStrings) {
- this(keepStrings, "content", false);
- }
-
- /**
- * Configure the parser string processing to try and convert XML values to JSON values and
- * use the passed CDATA Tag Name the processing value. Pass null to
- * disable CDATA processing
- * @param cDataTagName null to disable CDATA processing. Any other value
- * to use that value as the JSONObject key name to process as CDATA.
- * @deprecated This constructor has been deprecated in favor of using the new builder
- * pattern for the configuration.
- * This constructor may be removed in a future release.
- */
- @Deprecated
- public XMLParserConfiguration (final String cDataTagName) {
- this(false, cDataTagName, false);
- }
-
- /**
- * Configure the parser to use custom settings.
- * @param keepStrings true to parse all values as string.
- * false to try and convert XML string values into a JSON value.
- * @param cDataTagName null to disable CDATA processing. Any other value
- * to use that value as the JSONObject key name to process as CDATA.
- * @deprecated This constructor has been deprecated in favor of using the new builder
- * pattern for the configuration.
- * This constructor may be removed in a future release.
- */
- @Deprecated
- public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
- super(keepStrings, DEFAULT_MAXIMUM_NESTING_DEPTH);
- this.cDataTagName = cDataTagName;
- this.convertNilAttributeToNull = false;
- }
-
- /**
- * Configure the parser to use custom settings.
- * @param keepStrings true to parse all values as string.
- * false to try and convert XML string values into a JSON value.
- * @param cDataTagName null to disable CDATA processing. Any other value
- * to use that value as the JSONObject key name to process as CDATA.
- * @param convertNilAttributeToNull true to parse values with attribute xsi:nil="true" as null.
- * false to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
- * @deprecated This constructor has been deprecated in favor of using the new builder
- * pattern for the configuration.
- * This constructor may be removed or marked private in a future release.
- */
- @Deprecated
- public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
- super(false, DEFAULT_MAXIMUM_NESTING_DEPTH);
- this.keepNumberAsString = keepStrings;
- this.keepBooleanAsString = keepStrings;
- this.cDataTagName = cDataTagName;
- this.convertNilAttributeToNull = convertNilAttributeToNull;
- }
-
- /**
- * Configure the parser to use custom settings.
- * @param keepStrings true to parse all values as string.
- * false to try and convert XML string values into a JSON value.
- * @param cDataTagName null to disable CDATA processing. Any other value
- * to use that value as the JSONObject key name to process as CDATA.
- * @param convertNilAttributeToNull true to parse values with attribute xsi:nil="true" as null.
- * false to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
- * @param xsiTypeMap new HashMap>() to parse values with attribute
- * xsi:type="integer" as integer, xsi:type="string" as string
- * @param forceList new HashSet() to parse the provided tags' values as arrays
- * @param maxNestingDepth int to limit the nesting depth
- * @param closeEmptyTag boolean to turn on explicit end tag for tag with empty value
- */
- private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
- final boolean convertNilAttributeToNull, final Map> xsiTypeMap, final Set forceList,
- final int maxNestingDepth, final boolean closeEmptyTag, final boolean keepNumberAsString, final boolean keepBooleanAsString) {
- super(false, maxNestingDepth);
- this.keepNumberAsString = keepNumberAsString;
- this.keepBooleanAsString = keepBooleanAsString;
- this.cDataTagName = cDataTagName;
- this.convertNilAttributeToNull = convertNilAttributeToNull;
- this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
- this.forceList = Collections.unmodifiableSet(forceList);
- this.closeEmptyTag = closeEmptyTag;
- }
-
- /**
- * Provides a new instance of the same configuration.
- */
- @Override
- protected XMLParserConfiguration 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.
- final XMLParserConfiguration config = new XMLParserConfiguration(
- this.keepStrings,
- this.cDataTagName,
- this.convertNilAttributeToNull,
- this.xsiTypeMap,
- this.forceList,
- this.maxNestingDepth,
- this.closeEmptyTag,
- this.keepNumberAsString,
- this.keepBooleanAsString
- );
- config.shouldTrimWhiteSpace = this.shouldTrimWhiteSpace;
- return config;
- }
-
- /**
- * When parsing the XML into JSON, specifies if values should be kept as strings (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string)
- *
- * @param newVal
- * new value to use for the keepStrings configuration option.
- *
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- @SuppressWarnings("unchecked")
- @Override
- public XMLParserConfiguration withKeepStrings(final boolean newVal) {
- XMLParserConfiguration newConfig = this.clone();
- newConfig.keepStrings = newVal;
- newConfig.keepNumberAsString = newVal;
- newConfig.keepBooleanAsString = newVal;
- return newConfig;
- }
-
- /**
- * When parsing the XML into JSON, specifies if numbers should be kept as strings (1), or if
- * they should try to be guessed into JSON values (numeric, boolean, string)
- *
- * @param newVal
- * new value to use for the keepNumberAsString configuration option.
- *
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public XMLParserConfiguration withKeepNumberAsString(final boolean newVal) {
- XMLParserConfiguration newConfig = this.clone();
- newConfig.keepNumberAsString = newVal;
- newConfig.keepStrings = newConfig.keepBooleanAsString && newConfig.keepNumberAsString;
- return newConfig;
- }
-
- /**
- * When parsing the XML into JSON, specifies if booleans should be kept as strings (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string)
- *
- * @param newVal
- * new value to use for the withKeepBooleanAsString configuration option.
- *
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public XMLParserConfiguration withKeepBooleanAsString(final boolean newVal) {
- XMLParserConfiguration newConfig = this.clone();
- newConfig.keepBooleanAsString = newVal;
- newConfig.keepStrings = newConfig.keepBooleanAsString && newConfig.keepNumberAsString;
- return newConfig;
- }
-
- /**
- * 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 null to indicate no CDATA
- * processing.
- *
- * @return The cDataTagName configuration value.
- */
- public String getcDataTagName() {
- return this.cDataTagName;
- }
-
- /**
- * When parsing the XML into JSONML, specifies if numbers should be kept as strings (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string).
- *
- * @return The keepStrings configuration value.
- */
- public boolean isKeepNumberAsString() {
- return this.keepNumberAsString;
- }
-
- /**
- * When parsing the XML into JSONML, specifies if booleans should be kept as strings (true), or if
- * they should try to be guessed into JSON values (numeric, boolean, string).
- *
- * @return The keepStrings configuration value.
- */
- public boolean isKeepBooleanAsString() {
- return this.keepBooleanAsString;
- }
-
- /**
- * 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 null to indicate no CDATA
- * processing.
- *
- * @param newVal
- * new value to use for the cDataTagName configuration option.
- *
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public XMLParserConfiguration withcDataTagName(final String newVal) {
- XMLParserConfiguration newConfig = this.clone();
- newConfig.cDataTagName = newVal;
- return newConfig;
- }
-
- /**
- * When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
- * should be kept as attribute(false), or they should be converted to
- * null(true)
- *
- * @return The convertNilAttributeToNull configuration value.
- */
- public boolean isConvertNilAttributeToNull() {
- return this.convertNilAttributeToNull;
- }
-
- /**
- * When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
- * should be kept as attribute(false), or they should be converted to
- * null(true)
- *
- * @param newVal
- * new value to use for the convertNilAttributeToNull configuration option.
- *
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal) {
- XMLParserConfiguration newConfig = this.clone();
- newConfig.convertNilAttributeToNull = newVal;
- return newConfig;
- }
-
- /**
- * When parsing the XML into JSON, specifies that the values with attribute xsi:type
- * will be converted to target type defined to client in this configuration
- * {@code Map>} to parse values with attribute
- * xsi:type="integer" as integer, xsi:type="string" as string
- * @return xsiTypeMap unmodifiable configuration map.
- */
- public Map> getXsiTypeMap() {
- return this.xsiTypeMap;
- }
-
- /**
- * When parsing the XML into JSON, specifies that the values with attribute xsi:type
- * will be converted to target type defined to client in this configuration
- * {@code Map>} to parse values with attribute
- * xsi:type="integer" as integer, xsi:type="string" as string
- * @param xsiTypeMap {@code new HashMap>()} to parse values with attribute
- * xsi:type="integer" as integer, xsi:type="string" as string
- * @return The existing configuration will not be modified. A new configuration is returned.
- */
- public XMLParserConfiguration withXsiTypeMap(final Map> xsiTypeMap) {
- XMLParserConfiguration newConfig = this.clone();
- Map> cloneXsiTypeMap = new HashMap>(xsiTypeMap);
- newConfig.xsiTypeMap = Collections.unmodifiableMap(cloneXsiTypeMap);
- return newConfig;
- }
-
- /**
- * When parsing the XML into JSON, specifies that tags that will be converted to arrays
- * in this configuration {@code Set} to parse the provided tags' values as arrays
- * @return forceList unmodifiable configuration set.
- */
- public Set getForceList() {
- return this.forceList;
- }
-
- /**
- * When parsing the XML into JSON, specifies that tags that will be converted to arrays
- * in this configuration {@code Set} to parse the provided tags' values as arrays
- * @param forceList {@code new HashSet()} 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 forceList) {
- XMLParserConfiguration newConfig = this.clone();
- Set cloneForceList = new HashSet(forceList);
- 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.
- */
- @SuppressWarnings("unchecked")
- @Override
- public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
- return super.withMaxNestingDepth(maxNestingDepth);
- }
-
- /**
- * To enable explicit end tag with empty value.
- * @param closeEmptyTag new value for the closeEmptyTag property
- * @return same instance of configuration with empty tag config updated
- */
- public XMLParserConfiguration withCloseEmptyTag(boolean closeEmptyTag){
- XMLParserConfiguration clonedConfiguration = this.clone();
- clonedConfiguration.closeEmptyTag = closeEmptyTag;
- return clonedConfiguration;
- }
-
- /**
- * Sets whether whitespace should be trimmed inside of tags. *NOTE* Do not use this if
- * you expect your XML tags to have names that are the same as cDataTagName as this is unsupported.
- * cDataTagName should be set to a distinct value in these cases.
- * @param shouldTrimWhiteSpace boolean to set trimming on or off. Off is default.
- * @return same instance of configuration with empty tag config updated
- */
- public XMLParserConfiguration withShouldTrimWhitespace(boolean shouldTrimWhiteSpace){
- XMLParserConfiguration clonedConfiguration = this.clone();
- clonedConfiguration.shouldTrimWhiteSpace = shouldTrimWhiteSpace;
- return clonedConfiguration;
- }
-
- /**
- * Checks if the parser should automatically close empty XML tags.
- *
- * @return {@code true} if empty XML tags should be automatically closed, {@code false} otherwise.
- */
- public boolean isCloseEmptyTag() {
- return this.closeEmptyTag;
- }
-
- /**
- * Checks if the parser should trim white spaces from XML content.
- *
- * @return {@code true} if white spaces should be trimmed, {@code false} otherwise.
- */
- public boolean shouldTrimWhiteSpace() {
- return this.shouldTrimWhiteSpace;
- }
-}
diff --git a/src/main/java/org/json/XMLTokener.java b/src/main/java/org/json/XMLTokener.java
deleted file mode 100644
index bc18b31c9..000000000
--- a/src/main/java/org/json/XMLTokener.java
+++ /dev/null
@@ -1,410 +0,0 @@
-package org.json;
-
-/*
-Public Domain.
-*/
-
-import java.io.Reader;
-
-/**
- * The XMLTokener extends the JSONTokener to provide additional methods
- * for the parsing of XML texts.
- * @author JSON.org
- * @version 2015-12-09
- */
-public class XMLTokener extends JSONTokener {
-
-
- /** The table of entity values. It initially contains Character values for
- * amp, apos, gt, lt, quot.
- */
- public static final java.util.HashMap entity;
-
- private XMLParserConfiguration configuration = XMLParserConfiguration.ORIGINAL;
-
- static {
- entity = new java.util.HashMap(8);
- entity.put("amp", XML.AMP);
- entity.put("apos", XML.APOS);
- entity.put("gt", XML.GT);
- entity.put("lt", XML.LT);
- entity.put("quot", XML.QUOT);
- }
-
- /**
- * Construct an XMLTokener from a Reader.
- * @param r A source reader.
- */
- public XMLTokener(Reader r) {
- super(r);
- }
-
- /**
- * Construct an XMLTokener from a string.
- * @param s A source string.
- */
- public XMLTokener(String s) {
- super(s);
- }
-
- /**
- * Construct an XMLTokener from a Reader and an XMLParserConfiguration.
- * @param r A source reader.
- * @param configuration the configuration that can be used to set certain flags
- */
- public XMLTokener(Reader r, XMLParserConfiguration configuration) {
- super(r);
- this.configuration = configuration;
- }
-
- /**
- * Get the text in the CDATA block.
- * @return The string up to the ]]>.
- * @throws JSONException If the ]]> is not found.
- */
- public String nextCDATA() throws JSONException {
- char c;
- int i;
- StringBuilder sb = new StringBuilder();
- while (more()) {
- c = next();
- sb.append(c);
- i = sb.length() - 3;
- if (i >= 0 && sb.charAt(i) == ']' &&
- sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
- sb.setLength(i);
- return sb.toString();
- }
- }
- throw syntaxError("Unclosed CDATA");
- }
-
-
- /**
- * Get the next XML outer token, trimming whitespace. There are two kinds
- * of tokens: the {@code '<' } character which begins a markup
- * tag, and the content
- * text between markup tags.
- *
- * @return A string, or a {@code '<' } Character, or null if
- * there is no more source text.
- * @throws JSONException if a called function has an error
- */
- public Object nextContent() throws JSONException {
- char c;
- StringBuilder sb;
- do {
- c = next();
- } while (Character.isWhitespace(c) && configuration.shouldTrimWhiteSpace());
- if (c == 0) {
- return null;
- }
- if (c == '<') {
- return XML.LT;
- }
- sb = new StringBuilder();
- for (;;) {
- if (c == 0) {
- return sb.toString().trim();
- }
- if (c == '<') {
- back();
- if (configuration.shouldTrimWhiteSpace()) {
- return sb.toString().trim();
- } else return sb.toString();
- }
- if (c == '&') {
- sb.append(nextEntity(c));
- } else {
- sb.append(c);
- }
- c = next();
- }
- }
-
-
- /**
- * {@code
- * Return the next entity. These entities are translated to Characters:
- * & ' > < ".
- * }
- * @param ampersand An ampersand character.
- * @return A Character or an entity String if the entity is not recognized.
- * @throws JSONException If missing ';' in XML entity.
- */
- public Object nextEntity(@SuppressWarnings("unused") char ampersand) throws JSONException {
- StringBuilder sb = new StringBuilder();
- for (;;) {
- char c = next();
- if (Character.isLetterOrDigit(c) || c == '#') {
- sb.append(Character.toLowerCase(c));
- } else if (c == ';') {
- break;
- } else {
- throw syntaxError("Missing ';' in XML entity: &" + sb);
- }
- }
- String string = sb.toString();
- return unescapeEntity(string);
- }
-
- /**
- * Unescape an XML entity encoding;
- * @param e entity (only the actual entity value, not the preceding & or ending ;
- * @return
- */
- static String unescapeEntity(String e) {
- // validate
- if (e == null || e.isEmpty()) {
- return "";
- }
- // if our entity is an encoded unicode point, parse it.
- if (e.charAt(0) == '#') {
- int cp;
- if (e.charAt(1) == 'x' || e.charAt(1) == 'X') {
- // hex encoded unicode
- cp = Integer.parseInt(e.substring(2), 16);
- } else {
- // decimal encoded unicode
- cp = Integer.parseInt(e.substring(1));
- }
- return new String(new int[] {cp},0,1);
- }
- Character knownEntity = entity.get(e);
- if(knownEntity==null) {
- // we don't know the entity so keep it encoded
- return '&' + e + ';';
- }
- return knownEntity.toString();
- }
-
-
- /**
- * {@code
- * Returns the next XML meta token. This is used for skipping over
- * and ...?> structures.
- * }
- * @return {@code Syntax characters (< > / = ! ?) are returned as
- * Character, and strings and names are returned as Boolean. We don't care
- * what the values actually are.
- * }
- * @throws JSONException If a string is not properly closed or if the XML
- * is badly structured.
- */
- public Object nextMeta() throws JSONException {
- char c;
- char q;
- do {
- c = next();
- } while (Character.isWhitespace(c));
- switch (c) {
- case 0:
- throw syntaxError("Misshaped meta tag");
- case '<':
- return XML.LT;
- case '>':
- return XML.GT;
- case '/':
- return XML.SLASH;
- case '=':
- return XML.EQ;
- case '!':
- return XML.BANG;
- case '?':
- return XML.QUEST;
- case '"':
- case '\'':
- q = c;
- for (;;) {
- c = next();
- if (c == 0) {
- throw syntaxError("Unterminated string");
- }
- if (c == q) {
- return Boolean.TRUE;
- }
- }
- default:
- for (;;) {
- c = next();
- if (Character.isWhitespace(c)) {
- return Boolean.TRUE;
- }
- switch (c) {
- case 0:
- throw syntaxError("Unterminated string");
- case '<':
- case '>':
- case '/':
- case '=':
- case '!':
- case '?':
- case '"':
- case '\'':
- back();
- return Boolean.TRUE;
- }
- }
- }
- }
-
-
- /**
- * {@code
- * Get the next XML Token. These tokens are found inside of angle
- * brackets. It may be one of these characters: / > = ! ? or it
- * may be a string wrapped in single quotes or double quotes, or it may be a
- * name.
- * }
- * @return a String or a Character.
- * @throws JSONException If the XML is not well formed.
- */
- public Object nextToken() throws JSONException {
- char c;
- char q;
- StringBuilder sb;
- do {
- c = next();
- } while (Character.isWhitespace(c));
- switch (c) {
- case 0:
- throw syntaxError("Misshaped element");
- case '<':
- throw syntaxError("Misplaced '<'");
- case '>':
- return XML.GT;
- case '/':
- return XML.SLASH;
- case '=':
- return XML.EQ;
- case '!':
- return XML.BANG;
- case '?':
- return XML.QUEST;
-
-// Quoted string
-
- case '"':
- case '\'':
- q = c;
- sb = new StringBuilder();
- for (;;) {
- c = next();
- if (c == 0) {
- throw syntaxError("Unterminated string");
- }
- if (c == q) {
- return sb.toString();
- }
- if (c == '&') {
- sb.append(nextEntity(c));
- } else {
- sb.append(c);
- }
- }
- default:
-
-// Name
-
- sb = new StringBuilder();
- for (;;) {
- sb.append(c);
- c = next();
- if (Character.isWhitespace(c)) {
- return sb.toString();
- }
- switch (c) {
- case 0:
- return sb.toString();
- case '>':
- case '/':
- case '=':
- case '!':
- case '?':
- case '[':
- case ']':
- back();
- return sb.toString();
- case '<':
- case '"':
- case '\'':
- throw syntaxError("Bad character in a name");
- }
- }
- }
- }
-
-
- /**
- * Skip characters until past the requested string.
- * If it is not found, we are left at the end of the source with a result of false.
- * @param to A string to skip past.
- */
- // The Android implementation of JSONTokener has a public method of public void skipPast(String to)
- // even though ours does not have that method, to have API compatibility, our method in the subclass
- // should match.
- public void skipPast(String to) {
- boolean b;
- char c;
- int i;
- int j;
- int offset = 0;
- int length = to.length();
- char[] circle = new char[length];
-
- /*
- * First fill the circle buffer with as many characters as are in the
- * to string. If we reach an early end, bail.
- */
-
- for (i = 0; i < length; i += 1) {
- c = next();
- if (c == 0) {
- return;
- }
- circle[i] = c;
- }
-
- /* We will loop, possibly for all of the remaining characters. */
-
- for (;;) {
- j = offset;
- b = true;
-
- /* Compare the circle buffer with the to string. */
-
- for (i = 0; i < length; i += 1) {
- if (circle[j] != to.charAt(i)) {
- b = false;
- break;
- }
- j += 1;
- if (j >= length) {
- j -= length;
- }
- }
-
- /* If we exit the loop with b intact, then victory is ours. */
-
- if (b) {
- return;
- }
-
- /* Get the next character. If there isn't one, then defeat is ours. */
-
- c = next();
- if (c == 0) {
- return;
- }
- /*
- * Shove the character in the circle buffer and advance the
- * circle offset. The offset is mod n.
- */
- circle[offset] = c;
- offset += 1;
- if (offset >= length) {
- offset -= length;
- }
- }
- }
-}
diff --git a/src/main/java/org/json/XMLXsiTypeConverter.java b/src/main/java/org/json/XMLXsiTypeConverter.java
deleted file mode 100644
index ea6739d34..000000000
--- a/src/main/java/org/json/XMLXsiTypeConverter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.json;
-/*
-Public Domain.
-*/
-
-/**
- * Type conversion configuration interface to be used with xsi:type attributes.
- *
- * XML Sample
- * {@code
- *
- * 12345
- * 54321
- *
- * }
- * JSON Output
- * {@code
- * {
- * "root" : {
- * "asString" : "12345",
- * "asInt": 54321
- * }
- * }
- * }
- *
- * Usage
- * {@code
- * Map> xsiTypeMap = new HashMap>();
- * xsiTypeMap.put("string", new XMLXsiTypeConverter() {
- * @Override public String convert(final String value) {
- * return value;
- * }
- * });
- * xsiTypeMap.put("integer", new XMLXsiTypeConverter() {
- * @Override public Integer convert(final String value) {
- * return Integer.valueOf(value);
- * }
- * });
- * }
- *
- * @author kumar529
- * @param return type of convert method
- */
-public interface XMLXsiTypeConverter {
-
- /**
- * Converts an XML xsi:type attribute value to the specified type {@code T}.
- *
- * @param value The string representation of the XML xsi:type attribute value to be converted.
- * @return An object of type {@code T} representing the converted value.
- */
- T convert(String value);
-}
diff --git a/src/test/java/org/json/junit/CDLTest.java b/src/test/java/org/json/junit/CDLTest.java
deleted file mode 100644
index e5eb9eda8..000000000
--- a/src/test/java/org/json/junit/CDLTest.java
+++ /dev/null
@@ -1,392 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-import org.junit.Test;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONArray;
-import org.json.CDL;
-
-/**
- * Tests for CDL.java.
- * CDL provides an application level API, but it is not used by the
- * reference app. To test it, strings will be converted to JSON-Java classes
- * and then converted back.
- */
-public class CDLTest {
-
- /**
- * String of lines where the column names are in the first row,
- * and all subsequent rows are values. All keys and values should be legal.
- */
- private static final String LINES = "Col 1, Col 2, \tCol 3, Col 4, Col 5, Col 6, Col 7\n" +
- "val1, val2, val3, val4, val5, val6, val7\n" +
- "1, 2, 3, 4\t, 5, 6, 7\n" +
- "true, false, true, true, false, false, false\n" +
- "0.23, 57.42, 5e27, -234.879, 2.34e5, 0.0, 9e-3\n" +
- "\"va\tl1\", \"v\bal2\", \"val3\", \"val\f4\", \"val5\", \"va'l6\", val7\n";
-
-
- /**
- * CDL.toJSONArray() adds all values as strings, with no filtering or
- * conversions. For testing, this means that the expected JSONObject
- * values all must be quoted in the cases where the JSONObject parsing
- * might normally convert the value into a non-string.
- */
- private static final String EXPECTED_LINES =
- "[ " +
- "{" +
- "\"Col 1\":\"val1\", " +
- "\"Col 2\":\"val2\", " +
- "\"Col 3\":\"val3\", " +
- "\"Col 4\":\"val4\", " +
- "\"Col 5\":\"val5\", " +
- "\"Col 6\":\"val6\", " +
- "\"Col 7\":\"val7\"" +
- "}, " +
- " {" +
- "\"Col 1\":\"1\", " +
- "\"Col 2\":\"2\", " +
- "\"Col 3\":\"3\", " +
- "\"Col 4\":\"4\", " +
- "\"Col 5\":\"5\", " +
- "\"Col 6\":\"6\", " +
- "\"Col 7\":\"7\"" +
- "}, " +
- " {" +
- "\"Col 1\":\"true\", " +
- "\"Col 2\":\"false\", " +
- "\"Col 3\":\"true\", " +
- "\"Col 4\":\"true\", " +
- "\"Col 5\":\"false\", " +
- "\"Col 6\":\"false\", " +
- "\"Col 7\":\"false\"" +
- "}, " +
- "{" +
- "\"Col 1\":\"0.23\", " +
- "\"Col 2\":\"57.42\", " +
- "\"Col 3\":\"5e27\", " +
- "\"Col 4\":\"-234.879\", " +
- "\"Col 5\":\"2.34e5\", " +
- "\"Col 6\":\"0.0\", " +
- "\"Col 7\":\"9e-3\"" +
- "}, " +
- "{" +
- "\"Col 1\":\"va\tl1\", " +
- "\"Col 2\":\"v\bal2\", " +
- "\"Col 3\":\"val3\", " +
- "\"Col 4\":\"val\f4\", " +
- "\"Col 5\":\"val5\", " +
- "\"Col 6\":\"va'l6\", " +
- "\"Col 7\":\"val7\"" +
- "}" +
- "]";
-
- /**
- * Attempts to create a JSONArray from a null string.
- * Expect a NullPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void exceptionOnNullString() {
- String nullStr = null;
- CDL.toJSONArray(nullStr);
- }
-
- /**
- * Attempts to create a JSONArray from a string with unbalanced quotes
- * in column title line. Expects a JSONException.
- */
- @Test
- public void unbalancedQuoteInName() {
- String badLine = "Col1, \"Col2\nVal1, Val2";
- try {
- CDL.toJSONArray(badLine);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Missing close quote '\"'. at 12 [character 0 line 2]",
- e.getMessage());
- }
- }
-
- /**
- * Attempts to create a JSONArray from a string with unbalanced quotes
- * in value line. Expects a JSONException.
- */
- @Test
- public void unbalancedQuoteInValue() {
- String badLine = "Col1, Col2\n\"Val1, Val2";
- try {
- CDL.toJSONArray(badLine);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Missing close quote '\"'. at 22 [character 11 line 2]",
- e.getMessage());
-
- }
- }
-
- /**
- * Attempts to create a JSONArray from a string with null char
- * in column title line. Expects a JSONException.
- */
- @Test
- public void nullInName() {
- String badLine = "C\0ol1, Col2\nVal1, Val2";
- try {
- CDL.toJSONArray(badLine);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Bad character 'o' (111). at 2 [character 3 line 1]",
- e.getMessage());
-
- }
- }
-
- /**
- * Attempt to create a JSONArray with unbalanced quotes and a properly escaped doubled quote.
- * Expects a JSONException.
- */
- @Test
- public void unbalancedEscapedQuote(){
- String badLine = "Col1, Col2\n\"Val1, \"\"Val2\"\"";
- try {
- CDL.toJSONArray(badLine);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Missing close quote '\"'. at 26 [character 15 line 2]",
- e.getMessage());
-
- }
- }
-
- /**
- * Csv parsing skip last row if last field of this row is empty #943
- */
- @Test
- public void csvParsingCatchesLastRow(){
- String data = "Field 1,Field 2,Field 3\n" +
- "value11,value12,\n" +
- "value21,value22,";
-
- JSONArray jsonArray = CDL.toJSONArray(data);
-
- JSONArray expectedJsonArray = new JSONArray();
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("Field 1", "value11");
- jsonObject.put("Field 2", "value12");
- jsonObject.put("Field 3", "");
- expectedJsonArray.put(jsonObject);
-
- jsonObject = new JSONObject();
- jsonObject.put("Field 1", "value21");
- jsonObject.put("Field 2", "value22");
- jsonObject.put("Field 3", "");
- expectedJsonArray.put(jsonObject);
-
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- }
-
- /**
- * Assert that there is no error for a single escaped quote within a properly embedded quote.
- */
- @Test
- public void singleEscapedQuote(){
- String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"";
- JSONArray jsonArray = CDL.toJSONArray(singleEscape);
-
- String cdlStr = CDL.toString(jsonArray);
- assertTrue(cdlStr.contains("Col1"));
- assertTrue(cdlStr.contains("Col2"));
- assertTrue(cdlStr.contains("Val1"));
- assertTrue(cdlStr.contains("\"Val2"));
- }
-
- /**
- * Assert that there is no error for a single escaped quote within a properly
- * embedded quote when not the last value.
- */
- @Test
- public void singleEscapedQuoteMiddleString(){
- String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"\nVal 3,Val 4";
- JSONArray jsonArray = CDL.toJSONArray(singleEscape);
-
- String cdlStr = CDL.toString(jsonArray);
- assertTrue(cdlStr.contains("Col1"));
- assertTrue(cdlStr.contains("Col2"));
- assertTrue(cdlStr.contains("Val1"));
- assertTrue(cdlStr.contains("\"Val2"));
- }
-
- /**
- * Attempt to create a JSONArray with an escape quote and no enclosing quotes.
- * Expects a JSONException.
- */
- @Test
- public void badEscapedQuote(){
- String badLine = "Col1, Col2\nVal1, \"\"Val2";
-
- try {
- CDL.toJSONArray(badLine);
- fail("Expecting an exception");
- } catch (JSONException e) {
- //System.out.println("Message" + e.getMessage());
- assertEquals("Expecting an exception message",
- "Bad character 'V' (86). at 20 [character 9 line 2]",
- e.getMessage());
-
- }
-
- }
-
- /**
- * call toString with a null array
- */
- @Test(expected=NullPointerException.class)
- public void nullJSONArrayToString() {
- CDL.toString((JSONArray)null);
- }
-
- /**
- * Create a JSONArray from an empty string
- */
- @Test
- public void emptyString() {
- String emptyStr = "";
- JSONArray jsonArray = CDL.toJSONArray(emptyStr);
- assertNull("CDL should return null when the input string is empty", jsonArray);
- }
-
- /**
- * Create a JSONArray with only 1 row
- */
- @Test
- public void onlyColumnNames() {
- String columnNameStr = "col1, col2, col3";
- JSONArray jsonArray = CDL.toJSONArray(columnNameStr);
- assertNull("CDL should return null when only 1 row is given",
- jsonArray);
- }
-
- /**
- * Create a JSONArray from string containing only whitespace and commas
- */
- @Test
- public void emptyLinesToJSONArray() {
- String str = " , , , \n , , , ";
- JSONArray jsonArray = CDL.toJSONArray(str);
- assertNull("JSONArray should be null for no content",
- jsonArray);
- }
-
- /**
- * call toString with a null array
- */
- @Test
- public void emptyJSONArrayToString() {
- JSONArray jsonArray = new JSONArray();
- String str = CDL.toString(jsonArray);
- assertNull("CDL should return null for toString(null)",
- str);
- }
-
- /**
- * call toString with a null arrays for names and values
- */
- @Test
- public void nullJSONArraysToString() {
- String str = CDL.toString(null, null);
- assertNull("CDL should return null for toString(null)",
- str);
- }
-
- /**
- * Given a JSONArray that was not built by CDL, some chars may be
- * found that would otherwise be filtered out by CDL.
- */
- @Test
- public void checkSpecialChars() {
- JSONArray jsonArray = new JSONArray();
- JSONObject jsonObject = new JSONObject();
- jsonArray.put(jsonObject);
- // \r will be filtered from name
- jsonObject.put("Col \r1", "V1");
- // \r will be filtered from value
- jsonObject.put("Col 2", "V2\r");
- assertEquals("expected length should be 1", 1, jsonArray.length());
- String cdlStr = CDL.toString(jsonArray);
- jsonObject = jsonArray.getJSONObject(0);
- assertTrue(cdlStr.contains("\"Col 1\""));
- assertTrue(cdlStr.contains("Col 2"));
- assertTrue(cdlStr.contains("V1"));
- assertTrue(cdlStr.contains("\"V2\""));
- }
-
- /**
- * Create a JSONArray from a string of lines
- */
- @Test
- public void textToJSONArray() {
- JSONArray jsonArray = CDL.toJSONArray(LINES);
- JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- }
- @Test
- public void textToJSONArrayPipeDelimited() {
- char delimiter = '|';
- JSONArray jsonArray = CDL.toJSONArray(LINES.replaceAll(",", String.valueOf(delimiter)), delimiter);
- JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- }
-
- /**
- * Create a JSONArray from a JSONArray of titles and a
- * string of value lines
- */
- @Test
- public void jsonArrayToJSONArray() {
- String nameArrayStr = "[\"Col1\", \"Col2\"]";
- String values = "V1, V2";
- JSONArray nameJSONArray = new JSONArray(nameArrayStr);
- JSONArray jsonArray = CDL.toJSONArray(nameJSONArray, values);
- JSONArray expectedJsonArray = new JSONArray("[{\"Col1\":\"V1\",\"Col2\":\"V2\"}]");
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- }
-
- /**
- * Create a JSONArray from a string of lines,
- * then convert to string and then back to JSONArray
- */
- @Test
- public void textToJSONArrayAndBackToString() {
- JSONArray jsonArray = CDL.toJSONArray(LINES);
- String jsonStr = CDL.toString(jsonArray);
- JSONArray finalJsonArray = CDL.toJSONArray(jsonStr);
- JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
- Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
- }
-
- /**
- * Create a JSONArray from a string of lines,
- * then convert to string and then back to JSONArray
- * with a custom delimiter
- */
- @Test
- public void textToJSONArrayAndBackToStringCustomDelimiter() {
- JSONArray jsonArray = CDL.toJSONArray(LINES, ',');
- String jsonStr = CDL.toString(jsonArray, ';');
- JSONArray finalJsonArray = CDL.toJSONArray(jsonStr, ';');
- JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
- Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
- }
-
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/json/junit/CookieListTest.java b/src/test/java/org/json/junit/CookieListTest.java
deleted file mode 100644
index 0af96401b..000000000
--- a/src/test/java/org/json/junit/CookieListTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.json.*;
-import org.junit.Test;
-
-import com.jayway.jsonpath.*;
-
-/**
- * HTTP cookie specification RFC6265: http://tools.ietf.org/html/rfc6265
- *
- * A cookie list is a JSONObject whose members are presumed to be cookie
- * name/value pairs. Entries are unescaped while being added, and escaped in
- * the toString() output.
- * Unescaping means to convert %hh hex strings to the ascii equivalent
- * and converting '+' to ' '.
- * Escaping converts '+', '%', '=', ';' and ascii control chars to %hh hex strings.
- *
- * CookieList should not be considered as just a list of Cookie objects:
- * - CookieList stores a cookie name/value pair as a single entry; Cookie stores
- * it as 2 entries (key="name" and key="value").
- * - CookieList requires multiple name/value pairs as input; Cookie allows the
- * 'secure' name with no associated value
- * - CookieList has no special handling for attribute name/value pairs.
- */
-public class CookieListTest {
-
- /**
- * Attempts to create a CookieList from a null string.
- * Expects a NullPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void nullCookieListException() {
- String cookieStr = null;
- CookieList.toJSONObject(cookieStr);
- }
-
- /**
- * Attempts to create a CookieList from a malformed string.
- * Expects a JSONException.
- */
- @Test
- public void malFormedCookieListException() {
- String cookieStr = "thisCookieHasNoEqualsChar";
- try {
- CookieList.toJSONObject(cookieStr);
- fail("should throw an exception");
- } catch (JSONException e) {
- /**
- * Not sure of the missing char, but full string compare fails
- */
- assertEquals("Expecting an exception message",
- "Expected '=' and instead saw '' at 25 [character 26 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Creates a CookieList from an empty string.
- */
- @Test
- public void emptyStringCookieList() {
- String cookieStr = "";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- assertTrue(jsonObject.isEmpty());
- }
-
- /**
- * CookieList with the simplest cookie - a name/value pair with no delimiter.
- */
- @Test
- public void simpleCookieList() {
- String cookieStr = "SID=31d4d96e407aad42";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("Expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
- }
-
- /**
- * CookieList with a single a cookie which has a name/value pair and delimiter.
- */
- @Test
- public void simpleCookieListWithDelimiter() {
- String cookieStr = "SID=31d4d96e407aad42;";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("Expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
- }
-
- /**
- * CookieList with multiple cookies consisting of name/value pairs
- * with delimiters.
- */
- @Test
- public void multiPartCookieList() {
- String cookieStr =
- "name1=myCookieValue1; "+
- " name2=myCookieValue2;"+
- "name3=myCookieValue3;"+
- " name4=myCookieValue4; "+
- "name5=myCookieValue5;"+
- " name6=myCookieValue6;";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("Expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
- assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
- assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
- assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
- assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
- assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
- }
-
- /**
- * CookieList from a JSONObject with valid key and null value
- */
- @Test
- public void convertCookieListWithNullValueToString() {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("key", JSONObject.NULL);
- String cookieToStr = CookieList.toString(jsonObject);
- assertTrue("toString() should be empty", "".equals(cookieToStr));
- }
-
- /**
- * CookieList with multiple entries converted to a JSON document.
- */
- @Test
- public void convertCookieListToString() {
- String cookieStr =
- "name1=myCookieValue1; "+
- " name2=myCookieValue2;"+
- "name3=myCookieValue3;"+
- " name4=myCookieValue4; "+
- "name5=myCookieValue5;"+
- " name6=myCookieValue6;";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- // exercise CookieList.toString()
- String cookieListString = CookieList.toString(jsonObject);
- // have to convert it back for validation
- jsonObject = CookieList.toJSONObject(cookieListString);
-
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("Expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
- assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
- assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
- assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
- assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
- assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
- }
-
- /**
- * CookieList with multiple entries and some '+' chars and URL-encoded
- * values converted to a JSON document.
- */
- @Test
- public void convertEncodedCookieListToString() {
- String cookieStr =
- "name1=myCookieValue1; "+
- " name2=my+Cookie+Value+2;"+
- "name3=my%2BCookie%26Value%3B3%3D;"+
- " name4=my%25CookieValue4; "+
- "name5=myCookieValue5;"+
- " name6=myCookieValue6;";
- JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("Expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
- assertTrue("expected my Cookie Value 2", "my Cookie Value 2".equals(jsonObject.query("/name2")));
- assertTrue("expected my+Cookie&Value;3=", "my+Cookie&Value;3=".equals(jsonObject.query("/name3")));
- assertTrue("expected my%CookieValue4", "my%CookieValue4".equals(jsonObject.query("/name4")));
- assertTrue("expected my%CookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
- assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
- }
-}
diff --git a/src/test/java/org/json/junit/CookieTest.java b/src/test/java/org/json/junit/CookieTest.java
deleted file mode 100644
index edd8a7eeb..000000000
--- a/src/test/java/org/json/junit/CookieTest.java
+++ /dev/null
@@ -1,242 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-
-import org.json.*;
-import org.junit.Test;
-
-
-/**
- * HTTP cookie specification: RFC6265
- *
- * At its most basic, a cookie is a name=value pair. The value may be subdivided
- * into other cookies, but that is not tested here. The cookie may also include
- * certain named attributes, delimited by semicolons.
- *
- * The Cookie.toString() method emits certain attributes if present: expires,
- * domain, path, secure. All but secure are name-value pairs. Other attributes
- * are not included in the toString() output.
- *
- * A JSON-Java encoded cookie escapes '+', '%', '=', ';' with %hh values.
- */
-public class CookieTest {
-
- /**
- * Attempts to create a JSONObject from a null string.
- * Expects a NullPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void nullCookieException() {
- String cookieStr = null;
- Cookie.toJSONObject(cookieStr);
- }
-
- /**
- * Attempts to create a JSONObject from a cookie string with
- * no '=' char.
- * Expects a JSONException.
- */
- @Test
- public void malFormedNameValueException() {
- String cookieStr = "thisCookieHasNoEqualsChar";
- try {
- Cookie.toJSONObject(cookieStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Expected '=' and instead saw '' at 25 [character 26 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempts to create a JSONObject from a cookie string
- * with embedded ';' char.
- * Expects a JSONException.
- */
- @Test
- public void booleanAttribute() {
- String cookieStr = "this=Cookie;myAttribute";
- JSONObject jo = Cookie.toJSONObject(cookieStr);
- assertTrue("has key 'name'", jo.has("name"));
- assertTrue("has key 'value'", jo.has("value"));
- assertTrue("has key 'myAttribute'", jo.has("myattribute"));
- }
-
- /**
- * Attempts to create a JSONObject from an empty cookie string.
- * Note: Cookie throws an exception, but CookieList does not.
- * Expects a JSONException
- */
- @Test
- public void emptyStringCookieException() {
- String cookieStr = "";
- try {
- Cookie.toJSONObject(cookieStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Cookies must have a 'name'",
- e.getMessage());
- }
- }
- /**
- *
- * Attempts to create a JSONObject from an cookie string where the name is blank.
- * Note: Cookie throws an exception, but CookieList does not.
- * Expects a JSONException
- */
- @Test
- public void emptyNameCookieException() {
- String cookieStr = " = value ";
- try {
- Cookie.toJSONObject(cookieStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Cookies must have a 'name'",
- e.getMessage());
- }
- }
-
- /**
- * Cookie from a simple name/value pair with no delimiter
- */
- @Test
- public void simpleCookie() {
- String cookieStr = "SID=31d4d96e407aad42";
- String expectedCookieStr = "{\"name\":\"SID\",\"value\":\"31d4d96e407aad42\"}";
- JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
- JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Store a cookie with all of the supported attributes in a
- * JSONObject. The secure attribute, which has no value, is treated
- * as a boolean.
- */
- @Test
- public void multiPartCookie() {
- String cookieStr =
- "PH=deleted; "+
- " expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
- "path=/; "+
- " domain=.yahoo.com;"+
- "secure";
- String expectedCookieStr =
- "{"+
- "\"name\":\"PH\","+
- "\"value\":\"deleted\","+
- "\"path\":\"/\","+
- "\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
- "\"domain\":\".yahoo.com\","+
- "\"secure\":true"+
- "}";
- JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
- JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Cookie.toString() will emit the non-standard "thiswont=beIncluded"
- * attribute, and the attribute is still stored in the JSONObject.
- * This test confirms both behaviors.
- */
- @Test
- public void convertCookieToString() {
- String cookieStr =
- "PH=deleted; "+
- " expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
- "path=/; "+
- " domain=.yahoo.com;"+
- "thisWont=beIncluded;"+
- "secure";
- String expectedCookieStr =
- "{\"thiswont\":\"beIncluded\","+
- "\"path\":\"/\","+
- "\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
- "\"domain\":\".yahoo.com\","+
- "\"name\":\"PH\","+
- "\"secure\":true,"+
- "\"value\":\"deleted\"}";
- // Add the nonstandard attribute to the expected cookie string
- String expectedDirectCompareCookieStr = expectedCookieStr;
- // convert all strings into JSONObjects
- JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
- JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
- JSONObject expectedDirectCompareJsonObject =
- new JSONObject(expectedDirectCompareCookieStr);
- // emit the string
- String cookieToStr = Cookie.toString(jsonObject);
- // create a final JSONObject from the string
- JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
- // JSONObject should contain the nonstandard string
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedDirectCompareJsonObject);
- // JSONObject -> string -> JSONObject should not contain the nonstandard string
- Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
- }
-
- /**
- * A string may be URL-encoded when converting to JSONObject.
- * If found, '+' is converted to ' ', and %hh hex strings are converted
- * to their ascii char equivalents. This test confirms the decoding
- * behavior.
- */
- @Test
- public void convertEncodedCookieToString() {
- String cookieStr =
- "PH=deleted; "+
- " expires=Wed,+19-Mar-2014+17:53:53+GMT;"+
- "path=/%2Bthis/is%26/a/spec%3Bsegment%3D; "+
- " domain=.yahoo.com;"+
- "secure";
- String expectedCookieStr =
- "{\"path\":\"/+this/is&/a/spec;segment=\","+
- "\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
- "\"domain\":\".yahoo.com\","+
- "\"name\":\"PH\","+
- "\"secure\":true,"+
- "\"value\":\"deleted\"}";
- JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
- JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
- String cookieToStr = Cookie.toString(jsonObject);
- JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
- }
-
- /**
- * A public API method performs a URL encoding for selected chars
- * in a string. Control chars, '+', '%', '=', ';' are all encoded
- * as %hh hex strings. The string is also trimmed.
- * This test confirms that behavior.
- */
- @Test
- public void escapeString() {
- String str = " +%\r\n\t\b%=;;; ";
- String expectedStr = "%2b%25%0d%0a%09%08%25%3d%3b%3b%3b";
- String actualStr = Cookie.escape(str);
- assertTrue("expect escape() to encode correctly. Actual: " +actualStr+
- " expected: " +expectedStr, expectedStr.equals(actualStr));
- }
-
- /**
- * A public API method performs URL decoding for strings.
- * '+' is converted to space and %hh hex strings are converted to
- * their ascii equivalent values. The string is not trimmed.
- * This test confirms that behavior.
- */
- @Test
- public void unescapeString() {
- String str = " +%2b%25%0d%0a%09%08%25%3d%3b%3b%3b+ ";
- String expectedStr = " +%\r\n\t\b%=;;; ";
- String actualStr = Cookie.unescape(str);
- assertTrue("expect unescape() to decode correctly. Actual: " +actualStr+
- " expected: " +expectedStr, expectedStr.equals(actualStr));
- }
-}
diff --git a/src/test/java/org/json/junit/EnumTest.java b/src/test/java/org/json/junit/EnumTest.java
deleted file mode 100644
index 1496a636a..000000000
--- a/src/test/java/org/json/junit/EnumTest.java
+++ /dev/null
@@ -1,433 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.json.junit.data.MyEnum;
-import org.json.junit.data.MyEnumClass;
-import org.json.junit.data.MyEnumField;
-import org.junit.Test;
-
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.JsonPath;
-
-/**
- * Enums are not explicitly supported in JSON-Java. But because enums act like
- * classes, all required behavior is already be present in some form.
- * These tests explore how enum serialization works with JSON-Java.
- */
-public class EnumTest {
-
- /**
- * To serialize an enum by its getters, use the JSONObject Object constructor.
- * The JSONObject ctor handles enum like any other bean. A JSONobject
- * is created whose entries are the getter name/value pairs.
- */
- @Test
- public void jsonObjectFromEnum() {
- // If there are no getters then the object is empty.
- MyEnum myEnum = MyEnum.VAL2;
- JSONObject jsonObject = new JSONObject(myEnum);
- assertTrue("simple enum has no getters", jsonObject.isEmpty());
-
- // enum with a getters should create a non-empty object
- MyEnumField myEnumField = MyEnumField.VAL2;
- jsonObject = new JSONObject(myEnumField);
-
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider()
- .parse(jsonObject.toString());
- assertTrue("expecting 2 items in top level object", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expecting val 2", "val 2".equals(jsonObject.query("/value")));
- assertTrue("expecting 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
-
- /**
- * class which contains enum instances. Each enum should be stored
- * in its own JSONObject
- */
- MyEnumClass myEnumClass = new MyEnumClass();
- myEnumClass.setMyEnum(MyEnum.VAL1);
- myEnumClass.setMyEnumField(MyEnumField.VAL3);
- jsonObject = new JSONObject(myEnumClass);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected 2 myEnumField items", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
- assertTrue("expected 0 myEnum items", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
-
- assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
- assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
- }
-
- /**
- * To serialize an enum by its set of allowed values, use getNames()
- * and the JSONObject Object with names constructor.
- */
- @Test
- public void jsonObjectFromEnumWithNames() {
- String [] names;
- JSONObject jsonObject;
-
- MyEnum myEnum = MyEnum.VAL1;
- names = JSONObject.getNames(myEnum);
- // The values will be MyEnum fields
- jsonObject = new JSONObject(myEnum, names);
-
- // validate JSON object
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 3 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
- assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
-
- MyEnumField myEnumField = MyEnumField.VAL3;
- names = JSONObject.getNames(myEnumField);
- // The values will be MyEnmField fields
- jsonObject = new JSONObject(myEnumField, names);
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 3 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
- assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
- assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
- }
-
- /**
- * Verify that enums are handled consistently between JSONArray and JSONObject
- */
- @Test
- public void verifyEnumConsistency(){
- JSONObject jo = new JSONObject();
-
- jo.put("value", MyEnumField.VAL2);
- String expected="{\"value\":\"VAL2\"}";
- String actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- jo.accumulate("value", MyEnumField.VAL1);
- expected="{\"value\":[\"VAL2\",\"VAL1\"]}";
- actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- jo.remove("value");
- jo.append("value", MyEnumField.VAL1);
- expected="{\"value\":[\"VAL1\"]}";
- actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- jo.put("value", EnumSet.of(MyEnumField.VAL2));
- expected="{\"value\":[\"VAL2\"]}";
- actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- JSONArray ja = new JSONArray();
- ja.put(MyEnumField.VAL2);
- jo.put("value", ja);
- actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- jo.put("value", new MyEnumField[]{MyEnumField.VAL2});
- actual = jo.toString();
- assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
-
- }
-
- /**
- * To serialize by assigned value, use the put() methods. The value
- * will be stored as a enum type.
- */
- @Test
- public void enumPut() {
- JSONObject jsonObject = new JSONObject();
- MyEnum myEnum = MyEnum.VAL2;
- jsonObject.put("myEnum", myEnum);
- MyEnumField myEnumField = MyEnumField.VAL1;
- jsonObject.putOnce("myEnumField", myEnumField);
-
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level objects", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
- assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/myEnumField")));
-
- JSONArray jsonArray = new JSONArray();
- jsonArray.put(myEnum);
- jsonArray.put(1, myEnumField);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 2 top level objects", ((List>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
- assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonArray.query("/1")));
-
- /**
- * Leaving these tests because they exercise get, opt, and remove
- */
- assertTrue("expecting myEnum value", MyEnum.VAL2.equals(jsonArray.get(0)));
- assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.opt(1)));
- assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.remove(1)));
- }
-
- /**
- * The default action of valueToString() is to call object.toString().
- * For enums, this means the assigned value will be returned as a string.
- */
- @Test
- public void enumValueToString() {
- String expectedStr1 = "\"VAL1\"";
- String expectedStr2 = "\"VAL1\"";
- MyEnum myEnum = MyEnum.VAL1;
- MyEnumField myEnumField = MyEnumField.VAL1;
- MyEnumClass myEnumClass = new MyEnumClass();
-
- String str1 = JSONObject.valueToString(myEnum);
- assertTrue("actual myEnum: "+str1+" expected: "+expectedStr1,
- str1.equals(expectedStr1));
- String str2 = JSONObject.valueToString(myEnumField);
- assertTrue("actual myEnumField: "+str2+" expected: "+expectedStr2,
- str2.equals(expectedStr2));
-
- /**
- * However, an enum within another class will not be rendered
- * unless that class overrides default toString()
- */
- String expectedStr3 = "\"org.json.junit.data.MyEnumClass@";
- myEnumClass.setMyEnum(MyEnum.VAL1);
- myEnumClass.setMyEnumField(MyEnumField.VAL1);
- String str3 = JSONObject.valueToString(myEnumClass);
- assertTrue("actual myEnumClass: "+str3+" expected: "+expectedStr3,
- str3.startsWith(expectedStr3));
- }
-
- /**
- * In whatever form the enum was added to the JSONObject or JSONArray,
- * json[Object|Array].toString should serialize it in a reasonable way.
- */
- @Test
- public void enumToString() {
- MyEnum myEnum = MyEnum.VAL2;
- JSONObject jsonObject = new JSONObject(myEnum);
- String expectedStr = "{}";
- assertTrue("myEnum toString() should be empty", expectedStr.equals(jsonObject.toString()));
-
- MyEnumField myEnumField = MyEnumField.VAL2;
- jsonObject = new JSONObject(myEnumField);
-
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected val 2", "val 2".equals(jsonObject.query("/value")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
-
- MyEnumClass myEnumClass = new MyEnumClass();
- myEnumClass.setMyEnum(MyEnum.VAL1);
- myEnumClass.setMyEnumField(MyEnumField.VAL3);
- jsonObject = new JSONObject(myEnumClass);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
- assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
-
- String [] names = JSONObject.getNames(myEnum);
- jsonObject = new JSONObject(myEnum, names);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 3 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
- assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
-
- names = JSONObject.getNames(myEnumField);
- jsonObject = new JSONObject(myEnumField, names);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 3 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
- assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
- assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
-
- expectedStr = "{\"myEnum\":\"VAL2\", \"myEnumField\":\"VAL2\"}";
- jsonObject = new JSONObject();
- jsonObject.putOpt("myEnum", myEnum);
- jsonObject.putOnce("myEnumField", myEnumField);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
- assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/myEnumField")));
-
- JSONArray jsonArray = new JSONArray();
- jsonArray.put(myEnum);
- jsonArray.put(1, myEnumField);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 2 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
- assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonArray.query("/1")));
- }
-
- /**
- * Wrap should handle enums exactly as a value type like Integer, Boolean, or String.
- */
- @Test
- public void wrap() {
- assertTrue("simple enum has no getters", JSONObject.wrap(MyEnum.VAL2) instanceof MyEnum);
-
- MyEnumField myEnumField = MyEnumField.VAL2;
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("enum",myEnumField);
-
- // validate JSON content
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 1 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/enum")));
-
- MyEnumClass myEnumClass = new MyEnumClass();
- myEnumClass.setMyEnum(MyEnum.VAL1);
- myEnumClass.setMyEnumField(MyEnumField.VAL3);
- jsonObject = (JSONObject)JSONObject.wrap(myEnumClass);
-
- // validate JSON content
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
- assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
-
- assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
- assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
- }
-
- /**
- * It was determined that some API methods should be added to
- * support enums:
- * JSONObject.getEnum(class, key)
- * JSONObject.optEnum(class, key)
- * JSONObject.optEnum(class, key, default)
- * JSONArray.getEnum(class, index)
- * JSONArray.optEnum(class, index)
- * JSONArray.optEnum(class, index, default)
- *
- * Exercise these enum API methods on JSONObject and JSONArray
- */
- @Test
- public void enumAPI() {
- MyEnumClass myEnumClass = new MyEnumClass();
- myEnumClass.setMyEnum(MyEnum.VAL1);
- MyEnumField myEnumField = MyEnumField.VAL2;
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("strKey", "value");
- jsonObject.put("strKey2", "VAL1");
- jsonObject.put("enumKey", myEnumField);
- jsonObject.put("enumClassKey", myEnumClass);
-
- // get a plain old enum
- MyEnumField actualEnum = jsonObject.getEnum(MyEnumField.class, "enumKey");
- assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
-
- // try to get the wrong value
- try {
- actualEnum = jsonObject.getEnum(MyEnumField.class, "strKey");
- assertTrue("should throw an exception for wrong key", false);
- } catch (Exception ignored) {}
-
- // get a class that contains an enum
- MyEnumClass actualEnumClass = (MyEnumClass)jsonObject.get("enumClassKey");
- assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
-
- // opt a plain old enum
- actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey");
- assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
-
- // opt the wrong value
- actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey");
- assertTrue("opt null", actualEnum == null);
-
- // opt a class that contains an enum
- actualEnumClass = (MyEnumClass)jsonObject.opt("enumClassKey");
- assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
-
- // opt with default a plain old enum
- actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey", null);
- assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
-
- // opt with default the wrong value
- actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey", null);
- assertNull("opt null", actualEnum);
-
- // opt with default the string value
- actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey2", null);
- assertEquals(MyEnumField.VAL1, actualEnum);
-
- // opt with default an index that does not exist
- actualEnum = jsonObject.optEnum(MyEnumField.class, "noKey", null);
- assertNull("opt null", actualEnum);
-
- assertNull("Expected Null when the enum class is null",
- jsonObject.optEnum(null, "enumKey"));
-
- /**
- * Exercise the proposed enum API methods on JSONArray
- */
- JSONArray jsonArray = new JSONArray();
- jsonArray.put("value");
- jsonArray.put(myEnumField);
- jsonArray.put(myEnumClass);
-
- // get a plain old enum
- actualEnum = jsonArray.getEnum(MyEnumField.class, 1);
- assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
-
- // try to get the wrong value
- try {
- actualEnum = jsonArray.getEnum(MyEnumField.class, 0);
- assertTrue("should throw an exception for wrong index", false);
- } catch (Exception ignored) {}
-
- // get a class that contains an enum
- actualEnumClass = (MyEnumClass)jsonArray.get(2);
- assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
-
- // opt a plain old enum
- actualEnum = jsonArray.optEnum(MyEnumField.class, 1);
- assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
-
- // opt the wrong value
- actualEnum = jsonArray.optEnum(MyEnumField.class, 0);
- assertTrue("opt null", actualEnum == null);
-
- // opt a class that contains an enum
- actualEnumClass = (MyEnumClass)jsonArray.opt(2);
- assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
-
- // opt with default a plain old enum
- actualEnum = jsonArray.optEnum(MyEnumField.class, 1, null);
- assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
-
- // opt with default the wrong value
- actualEnum = jsonArray.optEnum(MyEnumField.class, 0, null);
- assertTrue("opt null", actualEnum == null);
-
- // opt with default an index that does not exist
- actualEnum = jsonArray.optEnum(MyEnumField.class, 3, null);
- assertTrue("opt null", actualEnum == null);
-
- }
-}
diff --git a/src/test/java/org/json/junit/HTTPTest.java b/src/test/java/org/json/junit/HTTPTest.java
deleted file mode 100644
index 703d5ad2f..000000000
--- a/src/test/java/org/json/junit/HTTPTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-
-import org.json.*;
-import org.junit.Test;
-
-
-/**
- * Unit tests for JSON-Java HTTP.java. See RFC7230.
- */
-public class HTTPTest {
-
- /**
- * Attempt to call HTTP.toJSONObject() with a null string
- * Expects a NUllPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void nullHTTPException() {
- String httpStr = null;
- HTTP.toJSONObject(httpStr);
- }
-
- /**
- * Attempt to call HTTP.toJSONObject() with a string containing
- * an empty object. Expects a JSONException.
- */
- @Test
- public void notEnoughHTTPException() {
- String httpStr = "{}";
- JSONObject jsonObject = new JSONObject(httpStr);
- try {
- HTTP.toString(jsonObject);
- assertTrue("Expected to throw exception", false);
- } catch (JSONException e) {
- assertTrue("Expecting an exception message",
- "Not enough material for an HTTP header.".equals(e.getMessage()));
- }
- }
-
- /**
- * Calling HTTP.toJSONObject() with an empty string will result in a
- * populated JSONObject with keys but no values for Request-URI, Method,
- * and HTTP-Version.
- */
- @Test
- public void emptyStringHTTPRequest() {
- String httpStr = "";
- String expectedHTTPStr = "{\"Request-URI\":\"\",\"Method\":\"\",\"HTTP-Version\":\"\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a Request-URI, Method,
- * and HTTP-Version.
- */
- @Test
- public void simpleHTTPRequest() {
- String httpStr = "GET /hello.txt HTTP/1.1";
- String expectedHTTPStr =
- "{\"Request-URI\":\"/hello.txt\",\"Method\":\"GET\",\"HTTP-Version\":\"HTTP/1.1\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a response string containing a
- * HTTP-Version, Status-Code, and Reason.
- */
- @Test
- public void simpleHTTPResponse() {
- String httpStr = "HTTP/1.1 200 OK";
- String expectedHTTPStr =
- "{\"HTTP-Version\":\"HTTP/1.1\",\"Status-Code\":\"200\",\"Reason-Phrase\":\"OK\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a full request string including
- * request headers.
- */
- @Test
- public void extendedHTTPRequest() {
- String httpStr =
- "POST /enlighten/calais.asmx HTTP/1.1\n"+
- "Host: api.opencalais.com\n"+
- "Content-Type: text/xml; charset=utf-8\n"+
- "Content-Length: 100\n"+
- "SOAPAction: \"http://clearforest.com/Enlighten\"";
- String expectedHTTPStr =
- "{"+
- "\"Request-URI\":\"/enlighten/calais.asmx\","+
- "\"Host\":\"api.opencalais.com\","+
- "\"Method\":\"POST\","+
- "\"HTTP-Version\":\"HTTP/1.1\","+
- "\"Content-Length\":\"100\","+
- "\"Content-Type\":\"text/xml; charset=utf-8\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- /**
- * Not too easy for JSONObject to parse a string with embedded quotes.
- * For the sake of the test, add it here.
- */
- expectedJsonObject.put("SOAPAction","\"http://clearforest.com/Enlighten\"");
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a full response string including
- * response headers.
- */
- @Test
- public void extendedHTTPResponse() {
- String httpStr =
- "HTTP/1.1 200 OK\n"+
- "Content-Type: text/xml; charset=utf-8\n"+
- "Content-Length: 100\n";
- String expectedHTTPStr =
- "{\"HTTP-Version\":\"HTTP/1.1\","+
- "\"Status-Code\":\"200\","+
- "\"Content-Length\":\"100\","+
- "\"Reason-Phrase\":\"OK\","+
- "\"Content-Type\":\"text/xml; charset=utf-8\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a full POST request string including
- * response headers, then convert it back into an HTTP string.
- */
- @Test
- public void convertHTTPRequestToString() {
- String httpStr =
- "POST /enlighten/calais.asmx HTTP/1.1\n"+
- "Host: api.opencalais.com\n"+
- "Content-Type: text/xml; charset=utf-8\n"+
- "Content-Length: 100";
- String expectedHTTPStr =
- "{"+
- "\"Request-URI\":\"/enlighten/calais.asmx\","+
- "\"Host\":\"api.opencalais.com\","+
- "\"Method\":\"POST\","+
- "\"HTTP-Version\":\"HTTP/1.1\","+
- "\"Content-Length\":\"100\","+
- "\"Content-Type\":\"text/xml; charset=utf-8\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- String httpToStr = HTTP.toString(jsonObject);
- /**
- * JSONObject objects to crlfs and any trailing chars.
- * For the sake of the test, simplify the resulting string
- */
- httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
- httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
- JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
- }
-
- /**
- * Call HTTP.toJSONObject() with a full response string including
- * response headers, then convert it back into an HTTP string.
- */
- @Test
- public void convertHTTPResponseToString() {
- String httpStr =
- "HTTP/1.1 200 OK\n"+
- "Content-Type: text/xml; charset=utf-8\n"+
- "Content-Length: 100\n";
- String expectedHTTPStr =
- "{\"HTTP-Version\":\"HTTP/1.1\","+
- "\"Status-Code\":\"200\","+
- "\"Content-Length\":\"100\","+
- "\"Reason-Phrase\":\"OK\","+
- "\"Content-Type\":\"text/xml; charset=utf-8\"}";
- JSONObject jsonObject = HTTP.toJSONObject(httpStr);
- JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
- String httpToStr = HTTP.toString(jsonObject);
- /**
- * JSONObject objects to crlfs and any trailing chars.
- * For the sake of the test, simplify the resulting string
- */
- httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
- httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
- JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
- Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
- }
-}
diff --git a/src/test/java/org/json/junit/JSONArrayTest.java b/src/test/java/org/json/junit/JSONArrayTest.java
deleted file mode 100644
index 429620396..000000000
--- a/src/test/java/org/json/junit/JSONArrayTest.java
+++ /dev/null
@@ -1,1547 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONParserConfiguration;
-import org.json.JSONPointerException;
-import org.json.JSONString;
-import org.json.JSONTokener;
-import org.json.ParserConfiguration;
-import org.json.junit.data.MyJsonString;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.JsonPath;
-
-
-/**
- * Tests for JSON-Java JSONArray.java
- */
-public class JSONArrayTest {
- private final String arrayStr =
- "["+
- "true,"+
- "false,"+
- "\"true\","+
- "\"false\","+
- "\"hello\","+
- "23.45e-4,"+
- "\"23.45\","+
- "42,"+
- "\"43\","+
- "["+
- "\"world\""+
- "],"+
- "{"+
- "\"key1\":\"value1\","+
- "\"key2\":\"value2\","+
- "\"key3\":\"value3\","+
- "\"key4\":\"value4\""+
- "},"+
- "0,"+
- "\"-1\""+
- "]";
-
- /**
- * Tests that the similar method is working as expected.
- */
- @Test
- public void verifySimilar() {
- final String string1 = "HasSameRef";
- final String string2 = "HasDifferentRef";
- JSONArray obj1 = new JSONArray()
- .put("abc")
- .put(string1)
- .put(2);
-
- JSONArray obj2 = new JSONArray()
- .put("abc")
- .put(string1)
- .put(3);
-
- JSONArray obj3 = new JSONArray()
- .put("abc")
- .put(new String(string1))
- .put(2);
-
- JSONArray obj4 = new JSONArray()
- .put("abc")
- .put(2.0)
- .put(new String(string1));
-
- JSONArray obj5 = new JSONArray()
- .put("abc")
- .put(2.0)
- .put(new String(string2));
-
- assertFalse("obj1-obj2 Should eval to false", obj1.similar(obj2));
- assertTrue("obj1-obj3 Should eval to true", obj1.similar(obj3));
- assertFalse("obj4-obj5 Should eval to false", obj4.similar(obj5));
- }
-
- /**
- * Attempt to create a JSONArray with a null string.
- * Expects a NullPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void nullException() {
- String str = null;
- assertNull("Should throw an exception", new JSONArray(str));
- }
-
- /**
- * Attempt to create a JSONArray with an empty string.
- * Expects a JSONException.
- */
- @Test
- public void emptyStr() {
- String str = "";
- try {
- assertNull("Should throw an exception", new JSONArray(str));
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "A JSONArray text must start with '[' at 0 [character 1 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempt to create a JSONArray with an unclosed array.
- * Expects an exception
- */
- @Test
- public void unclosedArray() {
- try {
- assertNull("Should throw an exception", new JSONArray("["));
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "Expected a ',' or ']' at 1 [character 2 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempt to create a JSONArray with an unclosed array.
- * Expects an exception
- */
- @Test
- public void unclosedArray2() {
- try {
- assertNull("Should throw an exception", new JSONArray("[\"test\""));
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "Expected a ',' or ']' at 7 [character 8 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempt to create a JSONArray with an unclosed array.
- * Expects an exception
- */
- @Test
- public void unclosedArray3() {
- try {
- assertNull("Should throw an exception", new JSONArray("[\"test\","));
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "Expected a ',' or ']' at 8 [character 9 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempt to create a JSONArray with a string as object that is
- * not a JSON array doc.
- * Expects a JSONException.
- */
- @Test
- public void badObject() {
- String str = "abc";
- try {
- assertNull("Should throw an exception", new JSONArray((Object)str));
- } catch (JSONException e) {
- assertTrue("Expected an exception message",
- "JSONArray initial value should be a string or collection or array.".
- equals(e.getMessage()));
- }
- }
-
- /**
- * Verifies that the constructor has backwards compatibility with RAW types pre-java5.
- */
- @Test
- public void verifyConstructor() {
-
- final JSONArray expected = new JSONArray("[10]");
-
- @SuppressWarnings("rawtypes")
- Collection myRawC = Collections.singleton(Integer.valueOf(10));
- JSONArray jaRaw = new JSONArray(myRawC);
-
- Collection myCInt = Collections.singleton(Integer.valueOf(10));
- JSONArray jaInt = new JSONArray(myCInt);
-
- Collection myCObj = Collections.singleton((Object) Integer
- .valueOf(10));
- JSONArray jaObj = new JSONArray(myCObj);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaInt));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObj));
- Util.checkJSONArrayMaps(expected);
- Util.checkJSONArrayMaps(jaObj);
- Util.checkJSONArrayMaps(jaRaw);
- Util.checkJSONArrayMaps(jaInt);
- }
-
- @Test
- public void jsonArrayByListWithNestedNullValue() {
- List> list = new ArrayList>();
- Map sub = new HashMap();
- sub.put("nullKey", null);
- list.add(sub);
- JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withUseNativeNulls(true);
- JSONArray jsonArray = new JSONArray(list, parserConfiguration);
- JSONObject subObject = jsonArray.getJSONObject(0);
- assertTrue(subObject.has("nullKey"));
- assertEquals(JSONObject.NULL, subObject.get("nullKey"));
- }
-
- /**
- * Tests consecutive calls to putAll with array and collection.
- */
- @Test
- public void verifyPutAll() {
- final JSONArray jsonArray = new JSONArray();
-
- // array
- int[] myInts = { 1, 2, 3, 4, 5 };
- jsonArray.putAll(myInts);
-
- assertEquals("int arrays lengths should be equal",
- jsonArray.length(),
- myInts.length);
-
- for (int i = 0; i < myInts.length; i++) {
- assertEquals("int arrays elements should be equal",
- myInts[i],
- jsonArray.getInt(i));
- }
-
- // collection
- List myList = Arrays.asList("one", "two", "three", "four", "five");
- jsonArray.putAll(myList);
-
- int len = myInts.length + myList.size();
-
- assertEquals("arrays lengths should be equal",
- jsonArray.length(),
- len);
-
- // collection as object
- @SuppressWarnings("RedundantCast")
- Object myListAsObject = (Object) myList;
- jsonArray.putAll(myListAsObject);
-
- for (int i = 0; i < myList.size(); i++) {
- assertEquals("collection elements should be equal",
- myList.get(i),
- jsonArray.getString(myInts.length + i));
- }
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Verifies that the put Collection has backwards compatibility with RAW types pre-java5.
- */
- @Test
- public void verifyPutCollection() {
-
- final JSONArray expected = new JSONArray("[[10]]");
-
- @SuppressWarnings("rawtypes")
- Collection myRawC = Collections.singleton(Integer.valueOf(10));
- JSONArray jaRaw = new JSONArray();
- jaRaw.put(myRawC);
-
- Collection myCObj = Collections.singleton((Object) Integer
- .valueOf(10));
- JSONArray jaObj = new JSONArray();
- jaObj.put(myCObj);
-
- Collection myCInt = Collections.singleton(Integer.valueOf(10));
- JSONArray jaInt = new JSONArray();
- jaInt.put(myCInt);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObj));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaInt));
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- jaRaw, jaObj, jaInt
- )));
- }
-
-
- /**
- * Verifies that the put Map has backwards compatibility with RAW types pre-java5.
- */
- @Test
- public void verifyPutMap() {
-
- final JSONArray expected = new JSONArray("[{\"myKey\":10}]");
-
- @SuppressWarnings("rawtypes")
- Map myRawC = Collections.singletonMap("myKey", Integer.valueOf(10));
- JSONArray jaRaw = new JSONArray();
- jaRaw.put(myRawC);
-
- Map myCStrObj = Collections.singletonMap("myKey",
- (Object) Integer.valueOf(10));
- JSONArray jaStrObj = new JSONArray();
- jaStrObj.put(myCStrObj);
-
- Map myCStrInt = Collections.singletonMap("myKey",
- Integer.valueOf(10));
- JSONArray jaStrInt = new JSONArray();
- jaStrInt.put(myCStrInt);
-
- Map, ?> myCObjObj = Collections.singletonMap((Object) "myKey",
- (Object) Integer.valueOf(10));
- JSONArray jaObjObj = new JSONArray();
- jaObjObj.put(myCObjObj);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrObj));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrInt));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObjObj));
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- expected, jaRaw, jaStrObj, jaStrInt, jaObjObj
- )));
- }
-
- /**
- * Create a JSONArray doc with a variety of different elements.
- * Confirm that the values can be accessed via the get[type]() API methods
- */
- @SuppressWarnings("boxing")
- @Test
- public void getArrayValues() {
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- // booleans
- assertTrue("Array true",
- true == jsonArray.getBoolean(0));
- assertTrue("Array false",
- false == jsonArray.getBoolean(1));
- assertTrue("Array string true",
- true == jsonArray.getBoolean(2));
- assertTrue("Array string false",
- false == jsonArray.getBoolean(3));
- // strings
- assertTrue("Array value string",
- "hello".equals(jsonArray.getString(4)));
- // doubles
- assertTrue("Array double",
- Double.valueOf(23.45e-4).equals(jsonArray.getDouble(5)));
- assertTrue("Array string double",
- Double.valueOf(23.45).equals(jsonArray.getDouble(6)));
- assertTrue("Array double can be float",
- Float.valueOf(23.45e-4f).equals(jsonArray.getFloat(5)));
- // ints
- assertTrue("Array value int",
- Integer.valueOf(42).equals(jsonArray.getInt(7)));
- assertTrue("Array value string int",
- Integer.valueOf(43).equals(jsonArray.getInt(8)));
- // nested objects
- JSONArray nestedJsonArray = jsonArray.getJSONArray(9);
- assertTrue("Array value JSONArray", nestedJsonArray != null);
- JSONObject nestedJsonObject = jsonArray.getJSONObject(10);
- assertTrue("Array value JSONObject", nestedJsonObject != null);
- // longs
- assertTrue("Array value long",
- Long.valueOf(0).equals(jsonArray.getLong(11)));
- assertTrue("Array value string long",
- Long.valueOf(-1).equals(jsonArray.getLong(12)));
-
- assertTrue("Array value null", jsonArray.isNull(-1));
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Create a JSONArray doc with a variety of different elements.
- * Confirm that attempting to get the wrong types via the get[type]()
- * API methods result in JSONExceptions
- */
- @Test
- public void failedGetArrayValues() {
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- try {
- jsonArray.getBoolean(4);
- assertTrue("expected getBoolean to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a boolean (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.get(-1);
- assertTrue("expected get to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[-1] not found.",e.getMessage());
- }
- try {
- jsonArray.getDouble(4);
- assertTrue("expected getDouble to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a double (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.getInt(4);
- assertTrue("expected getInt to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a int (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.getJSONArray(4);
- assertTrue("expected getJSONArray to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a JSONArray (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.getJSONObject(4);
- assertTrue("expected getJSONObject to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a JSONObject (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.getLong(4);
- assertTrue("expected getLong to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[4] is not a long (class java.lang.String : hello).",e.getMessage());
- }
- try {
- jsonArray.getString(5);
- assertTrue("expected getString to fail", false);
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray[5] is not a String (class java.math.BigDecimal : 0.002345).",e.getMessage());
- }
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * The JSON parser is permissive of unambiguous unquoted keys and values.
- * Such JSON text should be allowed, even if it does not strictly conform
- * to the spec. However, after being parsed, toString() should emit strictly
- * conforming JSON text.
- */
- @Test
- public void unquotedText() {
- String str = "[value1, something!, (parens), foo@bar.com, 23, 23+45]";
- List expected = Arrays.asList("value1", "something!", "(parens)", "foo@bar.com", 23, "23+45");
-
- // Test should fail if default strictMode is true, pass if false
- JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
- if (jsonParserConfiguration.isStrictMode()) {
- try {
- JSONArray jsonArray = new JSONArray(str);
- assertEquals("Expected to throw exception due to invalid string", true, false);
- } catch (JSONException e) { }
- } else {
- JSONArray jsonArray = new JSONArray(str);
- assertEquals(expected, jsonArray.toList());
- }
- }
-
- /**
- * Exercise JSONArray.join() by converting a JSONArray into a
- * comma-separated string. Since this is very nearly a JSON document,
- * array braces are added to the beginning and end prior to validation.
- */
- @Test
- public void join() {
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- String joinStr = jsonArray.join(",");
-
- // validate JSON
- /**
- * Don't need to remake the JSONArray to perform the parsing
- */
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse("["+joinStr+"]");
- assertTrue("expected 13 items in top level object", ((List>)(JsonPath.read(doc, "$"))).size() == 13);
- assertTrue("expected true", Boolean.TRUE.equals(jsonArray.query("/0")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonArray.query("/1")));
- assertTrue("expected \"true\"", "true".equals(jsonArray.query("/2")));
- assertTrue("expected \"false\"", "false".equals(jsonArray.query("/3")));
- assertTrue("expected hello", "hello".equals(jsonArray.query("/4")));
- assertTrue("expected 0.002345", BigDecimal.valueOf(0.002345).equals(jsonArray.query("/5")));
- assertTrue("expected \"23.45\"", "23.45".equals(jsonArray.query("/6")));
- assertTrue("expected 42", Integer.valueOf(42).equals(jsonArray.query("/7")));
- assertTrue("expected \"43\"", "43".equals(jsonArray.query("/8")));
- assertTrue("expected 1 item in [9]", ((List>)(JsonPath.read(doc, "$[9]"))).size() == 1);
- assertTrue("expected world", "world".equals(jsonArray.query("/9/0")));
- assertTrue("expected 4 items in [10]", ((Map,?>)(JsonPath.read(doc, "$[10]"))).size() == 4);
- assertTrue("expected value1", "value1".equals(jsonArray.query("/10/key1")));
- assertTrue("expected value2", "value2".equals(jsonArray.query("/10/key2")));
- assertTrue("expected value3", "value3".equals(jsonArray.query("/10/key3")));
- assertTrue("expected value4", "value4".equals(jsonArray.query("/10/key4")));
- assertTrue("expected 0", Integer.valueOf(0).equals(jsonArray.query("/11")));
- assertTrue("expected \"-1\"", "-1".equals(jsonArray.query("/12")));
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Confirm the JSONArray.length() method
- */
- @Test
- public void length() {
- assertTrue("expected empty JSONArray length 0",
- new JSONArray().length() == 0);
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- assertTrue("expected JSONArray length 13. instead found "+jsonArray.length(), jsonArray.length() == 13);
- JSONArray nestedJsonArray = jsonArray.getJSONArray(9);
- assertTrue("expected JSONArray length 1", nestedJsonArray.length() == 1);
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- jsonArray, nestedJsonArray
- )));
- }
-
- /**
- * Create a JSONArray doc with a variety of different elements.
- * Confirm that the values can be accessed via the opt[type](index)
- * and opt[type](index, default) API methods.
- */
- @SuppressWarnings("boxing")
- @Test
- public void opt() {
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- assertTrue("Array opt value true",
- Boolean.TRUE == jsonArray.opt(0));
- assertTrue("Array opt value out of range",
- null == jsonArray.opt(-1));
-
- assertTrue("Array opt value out of range",
- null == jsonArray.opt(jsonArray.length()));
-
- assertTrue("Array opt boolean",
- Boolean.TRUE == jsonArray.optBoolean(0));
- assertTrue("Array opt boolean default",
- Boolean.FALSE == jsonArray.optBoolean(-1, Boolean.FALSE));
- assertTrue("Array opt boolean implicit default",
- Boolean.FALSE == jsonArray.optBoolean(-1));
-
- assertTrue("Array opt boolean object",
- Boolean.TRUE.equals(jsonArray.optBooleanObject(0)));
- assertTrue("Array opt boolean object default",
- Boolean.FALSE.equals(jsonArray.optBooleanObject(-1, Boolean.FALSE)));
- assertTrue("Array opt boolean object implicit default",
- Boolean.FALSE.equals(jsonArray.optBooleanObject(-1)));
-
- assertTrue("Array opt double",
- Double.valueOf(23.45e-4).equals(jsonArray.optDouble(5)));
- assertTrue("Array opt double default",
- Double.valueOf(1).equals(jsonArray.optDouble(0, 1)));
- assertTrue("Array opt double default implicit",
- Double.valueOf(jsonArray.optDouble(99)).isNaN());
-
- assertTrue("Array opt double object",
- Double.valueOf(23.45e-4).equals(jsonArray.optDoubleObject(5)));
- assertTrue("Array opt double object default",
- Double.valueOf(1).equals(jsonArray.optDoubleObject(0, 1D)));
- assertTrue("Array opt double object default implicit",
- jsonArray.optDoubleObject(99).isNaN());
-
- assertTrue("Array opt float",
- Float.valueOf(Double.valueOf(23.45e-4).floatValue()).equals(jsonArray.optFloat(5)));
- assertTrue("Array opt float default",
- Float.valueOf(1).equals(jsonArray.optFloat(0, 1)));
- assertTrue("Array opt float default implicit",
- Float.valueOf(jsonArray.optFloat(99)).isNaN());
-
- assertTrue("Array opt float object",
- Float.valueOf(23.45e-4F).equals(jsonArray.optFloatObject(5)));
- assertTrue("Array opt float object default",
- Float.valueOf(1).equals(jsonArray.optFloatObject(0, 1F)));
- assertTrue("Array opt float object default implicit",
- jsonArray.optFloatObject(99).isNaN());
-
- assertTrue("Array opt Number",
- BigDecimal.valueOf(23.45e-4).equals(jsonArray.optNumber(5)));
- assertTrue("Array opt Number default",
- Double.valueOf(1).equals(jsonArray.optNumber(0, 1d)));
- assertTrue("Array opt Number default implicit",
- Double.valueOf(jsonArray.optNumber(99,Double.NaN).doubleValue()).isNaN());
-
- assertTrue("Array opt int",
- Integer.valueOf(42).equals(jsonArray.optInt(7)));
- assertTrue("Array opt int default",
- Integer.valueOf(-1).equals(jsonArray.optInt(0, -1)));
- assertTrue("Array opt int default implicit",
- 0 == jsonArray.optInt(0));
-
- assertTrue("Array opt int object",
- Integer.valueOf(42).equals(jsonArray.optIntegerObject(7)));
- assertTrue("Array opt int object default",
- Integer.valueOf(-1).equals(jsonArray.optIntegerObject(0, -1)));
- assertTrue("Array opt int object default implicit",
- Integer.valueOf(0).equals(jsonArray.optIntegerObject(0)));
-
- JSONArray nestedJsonArray = jsonArray.optJSONArray(9);
- assertTrue("Array opt JSONArray", nestedJsonArray != null);
- assertTrue("Array opt JSONArray null",
- null == jsonArray.optJSONArray(99));
- assertTrue("Array opt JSONArray default",
- "value".equals(jsonArray.optJSONArray(99, new JSONArray("[\"value\"]")).getString(0)));
-
- JSONObject nestedJsonObject = jsonArray.optJSONObject(10);
- assertTrue("Array opt JSONObject", nestedJsonObject != null);
- assertTrue("Array opt JSONObject null",
- null == jsonArray.optJSONObject(99));
- assertTrue("Array opt JSONObject default",
- "value".equals(jsonArray.optJSONObject(99, new JSONObject("{\"key\":\"value\"}")).getString("key")));
-
- assertTrue("Array opt long",
- 0 == jsonArray.optLong(11));
- assertTrue("Array opt long default",
- -2 == jsonArray.optLong(-1, -2));
- assertTrue("Array opt long default implicit",
- 0 == jsonArray.optLong(-1));
-
- assertTrue("Array opt long object",
- Long.valueOf(0).equals(jsonArray.optLongObject(11)));
- assertTrue("Array opt long object default",
- Long.valueOf(-2).equals(jsonArray.optLongObject(-1, -2L)));
- assertTrue("Array opt long object default implicit",
- Long.valueOf(0).equals(jsonArray.optLongObject(-1)));
-
- assertTrue("Array opt string",
- "hello".equals(jsonArray.optString(4)));
- assertTrue("Array opt string default implicit",
- "".equals(jsonArray.optString(-1)));
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- jsonArray, nestedJsonArray
- )));
- Util.checkJSONObjectMaps(nestedJsonObject);
- }
-
- /**
- * Verifies that the opt methods properly convert string values.
- */
- @Test
- public void optStringConversion(){
- JSONArray ja = new JSONArray("[\"123\",\"true\",\"false\"]");
- assertTrue("unexpected optBoolean value",ja.optBoolean(1,false)==true);
- assertTrue("unexpected optBooleanObject value",Boolean.valueOf(true).equals(ja.optBooleanObject(1,false)));
- assertTrue("unexpected optBoolean value",ja.optBoolean(2,true)==false);
- assertTrue("unexpected optBooleanObject value",Boolean.valueOf(false).equals(ja.optBooleanObject(2,true)));
- assertTrue("unexpected optInt value",ja.optInt(0,0)==123);
- assertTrue("unexpected optIntegerObject value",Integer.valueOf(123).equals(ja.optIntegerObject(0,0)));
- assertTrue("unexpected optLong value",ja.optLong(0,0)==123);
- assertTrue("unexpected optLongObject value",Long.valueOf(123).equals(ja.optLongObject(0,0L)));
- assertTrue("unexpected optDouble value",ja.optDouble(0,0.0)==123.0);
- assertTrue("unexpected optDoubleObject value",Double.valueOf(123.0).equals(ja.optDoubleObject(0,0.0)));
- assertTrue("unexpected optBigInteger value",ja.optBigInteger(0,BigInteger.ZERO).compareTo(new BigInteger("123"))==0);
- assertTrue("unexpected optBigDecimal value",ja.optBigDecimal(0,BigDecimal.ZERO).compareTo(new BigDecimal("123"))==0);
- Util.checkJSONArrayMaps(ja);
- }
-
- /**
- * Exercise the JSONArray.put(value) method with various parameters
- * and confirm the resulting JSONArray.
- */
- @SuppressWarnings("boxing")
- @Test
- public void put() {
- JSONArray jsonArray = new JSONArray();
-
- // index 0
- jsonArray.put(true);
- // 1
- jsonArray.put(false);
-
- String jsonArrayStr =
- "["+
- "\"hello\","+
- "\"world\""+
- "]";
- // 2
- jsonArray.put(new JSONArray(jsonArrayStr));
-
- // 3
- jsonArray.put(2.5);
- // 4
- jsonArray.put(1);
- // 5
- jsonArray.put(45L);
-
- // 6
- jsonArray.put("objectPut");
-
- String jsonObjectStr =
- "{"+
- "\"key10\":\"val10\","+
- "\"key20\":\"val20\","+
- "\"key30\":\"val30\""+
- "}";
- JSONObject jsonObject = new JSONObject(jsonObjectStr);
- // 7
- jsonArray.put(jsonObject);
-
- Map map = new HashMap();
- map.put("k1", "v1");
- // 8
- jsonArray.put(map);
-
- Collection collection = new ArrayList();
- collection.add(1);
- collection.add(2);
- // 9
- jsonArray.put(collection);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 10 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 10);
- assertTrue("expected true", Boolean.TRUE.equals(jsonArray.query("/0")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonArray.query("/1")));
- assertTrue("expected 2 items in [2]", ((List>)(JsonPath.read(doc, "$[2]"))).size() == 2);
- assertTrue("expected hello", "hello".equals(jsonArray.query("/2/0")));
- assertTrue("expected world", "world".equals(jsonArray.query("/2/1")));
- assertTrue("expected 2.5", Double.valueOf(2.5).equals(jsonArray.query("/3")));
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/4")));
- assertTrue("expected 45", Long.valueOf(45).equals(jsonArray.query("/5")));
- assertTrue("expected objectPut", "objectPut".equals(jsonArray.query("/6")));
- assertTrue("expected 3 items in [7]", ((Map,?>)(JsonPath.read(doc, "$[7]"))).size() == 3);
- assertTrue("expected val10", "val10".equals(jsonArray.query("/7/key10")));
- assertTrue("expected val20", "val20".equals(jsonArray.query("/7/key20")));
- assertTrue("expected val30", "val30".equals(jsonArray.query("/7/key30")));
- assertTrue("expected 1 item in [8]", ((Map,?>)(JsonPath.read(doc, "$[8]"))).size() == 1);
- assertTrue("expected v1", "v1".equals(jsonArray.query("/8/k1")));
- assertTrue("expected 2 items in [9]", ((List>)(JsonPath.read(doc, "$[9]"))).size() == 2);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/9/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/9/1")));
- Util.checkJSONArrayMaps(jsonArray);
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONArray.put(index, value) method with various parameters
- * and confirm the resulting JSONArray.
- */
- @SuppressWarnings("boxing")
- @Test
- public void putIndex() {
- JSONArray jsonArray = new JSONArray();
-
- // 1
- jsonArray.put(1, false);
- // index 0
- jsonArray.put(0, true);
-
- String jsonArrayStr =
- "["+
- "\"hello\","+
- "\"world\""+
- "]";
- // 2
- jsonArray.put(2, new JSONArray(jsonArrayStr));
-
- // 5
- jsonArray.put(5, 45L);
- // 4
- jsonArray.put(4, 1);
- // 3
- jsonArray.put(3, 2.5);
-
- // 6
- jsonArray.put(6, "objectPut");
-
- // 7 will be null
-
- String jsonObjectStr =
- "{"+
- "\"key10\":\"val10\","+
- "\"key20\":\"val20\","+
- "\"key30\":\"val30\""+
- "}";
- JSONObject jsonObject = new JSONObject(jsonObjectStr);
- jsonArray.put(8, jsonObject);
- Collection collection = new ArrayList();
- collection.add(1);
- collection.add(2);
- jsonArray.put(9,collection);
-
- Map map = new HashMap();
- map.put("k1", "v1");
- jsonArray.put(10, map);
- try {
- jsonArray.put(-1, "abc");
- assertTrue("put index < 0 should have thrown exception", false);
- } catch(Exception ignored) {}
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 11 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 11);
- assertTrue("expected true", Boolean.TRUE.equals(jsonArray.query("/0")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonArray.query("/1")));
- assertTrue("expected 2 items in [2]", ((List>)(JsonPath.read(doc, "$[2]"))).size() == 2);
- assertTrue("expected hello", "hello".equals(jsonArray.query("/2/0")));
- assertTrue("expected world", "world".equals(jsonArray.query("/2/1")));
- assertTrue("expected 2.5", Double.valueOf(2.5).equals(jsonArray.query("/3")));
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/4")));
- assertTrue("expected 45", Long.valueOf(45).equals(jsonArray.query("/5")));
- assertTrue("expected objectPut", "objectPut".equals(jsonArray.query("/6")));
- assertTrue("expected null", JSONObject.NULL.equals(jsonArray.query("/7")));
- assertTrue("expected 3 items in [8]", ((Map,?>)(JsonPath.read(doc, "$[8]"))).size() == 3);
- assertTrue("expected val10", "val10".equals(jsonArray.query("/8/key10")));
- assertTrue("expected val20", "val20".equals(jsonArray.query("/8/key20")));
- assertTrue("expected val30", "val30".equals(jsonArray.query("/8/key30")));
- assertTrue("expected 2 items in [9]", ((List>)(JsonPath.read(doc, "$[9]"))).size() == 2);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/9/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/9/1")));
- assertTrue("expected 1 item in [10]", ((Map,?>)(JsonPath.read(doc, "$[10]"))).size() == 1);
- assertTrue("expected v1", "v1".equals(jsonArray.query("/10/k1")));
- Util.checkJSONObjectMaps(jsonObject);
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Exercise the JSONArray.remove(index) method
- * and confirm the resulting JSONArray.
- */
- @Test
- public void remove() {
- String arrayStr1 =
- "["+
- "1"+
- "]";
- JSONArray jsonArray = new JSONArray(arrayStr1);
- jsonArray.remove(0);
- assertTrue("array should be empty", null == jsonArray.remove(5));
- assertTrue("jsonArray should be empty", jsonArray.isEmpty());
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Exercise the JSONArray.similar() method with various parameters
- * and confirm the results when not similar.
- */
- @Test
- public void notSimilar() {
- String arrayStr1 =
- "["+
- "1"+
- "]";
- JSONArray jsonArray = new JSONArray(arrayStr1);
- JSONArray otherJsonArray = new JSONArray();
- assertTrue("arrays lengths differ", !jsonArray.similar(otherJsonArray));
-
- JSONObject jsonObject = new JSONObject("{\"k1\":\"v1\"}");
- JSONObject otherJsonObject = new JSONObject();
- jsonArray = new JSONArray();
- jsonArray.put(jsonObject);
- otherJsonArray = new JSONArray();
- otherJsonArray.put(otherJsonObject);
- assertTrue("arrays JSONObjects differ", !jsonArray.similar(otherJsonArray));
-
- JSONArray nestedJsonArray = new JSONArray("[1, 2]");
- JSONArray otherNestedJsonArray = new JSONArray();
- jsonArray = new JSONArray();
- jsonArray.put(nestedJsonArray);
- otherJsonArray = new JSONArray();
- otherJsonArray.put(otherNestedJsonArray);
- assertTrue("arrays nested JSONArrays differ",
- !jsonArray.similar(otherJsonArray));
-
- jsonArray = new JSONArray();
- jsonArray.put("hello");
- otherJsonArray = new JSONArray();
- otherJsonArray.put("world");
- assertTrue("arrays values differ",
- !jsonArray.similar(otherJsonArray));
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- jsonArray, otherJsonArray
- )));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject, otherJsonObject
- )));
- }
-
- /**
- * Exercise JSONArray toString() method with various indent levels.
- */
- @Test
- public void jsonArrayToStringIndent() {
- String jsonArray0Str =
- "[" +
- "[1,2," +
- "{\"key3\":true}" +
- "]," +
- "{\"key1\":\"val1\",\"key2\":" +
- "{\"key2\":\"val2\"}" +
- "}," +
- "[" +
- "[1,2.1]" +
- "," +
- "[null]" +
- "]" +
- "]";
-
- String jsonArray1Strs [] =
- {
- "[",
- " [",
- " 1,",
- " 2,",
- " {\"key3\": true}",
- " ],",
- " {",
- " \"key1\": \"val1\",",
- " \"key2\": {\"key2\": \"val2\"}",
- " },",
- " [",
- " [",
- " 1,",
- " 2.1",
- " ],",
- " [null]",
- " ]",
- "]"
- };
- String jsonArray4Strs [] =
- {
- "[",
- " [",
- " 1,",
- " 2,",
- " {\"key3\": true}",
- " ],",
- " {",
- " \"key1\": \"val1\",",
- " \"key2\": {\"key2\": \"val2\"}",
- " },",
- " [",
- " [",
- " 1,",
- " 2.1",
- " ],",
- " [null]",
- " ]",
- "]"
- };
- JSONArray jsonArray = new JSONArray(jsonArray0Str);
- String [] actualStrArray = jsonArray.toString().split("\\r?\\n");
- assertEquals("Expected 1 line", 1, actualStrArray.length);
- actualStrArray = jsonArray.toString(0).split("\\r?\\n");
- assertEquals("Expected 1 line", 1, actualStrArray.length);
-
- actualStrArray = jsonArray.toString(1).split("\\r?\\n");
- assertEquals("Expected lines", jsonArray1Strs.length, actualStrArray.length);
- List list = Arrays.asList(actualStrArray);
- for (String s : jsonArray1Strs) {
- list.contains(s);
- }
-
- actualStrArray = jsonArray.toString(4).split("\\r?\\n");
- assertEquals("Expected lines", jsonArray1Strs.length, actualStrArray.length);
- list = Arrays.asList(actualStrArray);
- for (String s : jsonArray4Strs) {
- list.contains(s);
- }
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Convert an empty JSONArray to JSONObject
- */
- @Test
- public void toJSONObject() {
- JSONArray names = new JSONArray();
- JSONArray jsonArray = new JSONArray();
- assertTrue("toJSONObject should return null",
- null == jsonArray.toJSONObject(names));
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- names, jsonArray
- )));
- }
-
- /**
- * Confirm the creation of a JSONArray from an array of ints
- */
- @Test
- public void objectArrayVsIsArray() {
- int[] myInts = { 1, 2, 3, 4, 5, 6, 7 };
- Object myObject = myInts;
- JSONArray jsonArray = new JSONArray(myObject);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 7 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 7);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/1")));
- assertTrue("expected 3", Integer.valueOf(3).equals(jsonArray.query("/2")));
- assertTrue("expected 4", Integer.valueOf(4).equals(jsonArray.query("/3")));
- assertTrue("expected 5", Integer.valueOf(5).equals(jsonArray.query("/4")));
- assertTrue("expected 6", Integer.valueOf(6).equals(jsonArray.query("/5")));
- assertTrue("expected 7", Integer.valueOf(7).equals(jsonArray.query("/6")));
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Exercise the JSONArray iterator.
- */
- @SuppressWarnings("boxing")
- @Test
- public void iteratorTest() {
- JSONArray jsonArray = new JSONArray(this.arrayStr);
- Iterator it = jsonArray.iterator();
- assertTrue("Array true",
- Boolean.TRUE.equals(it.next()));
- assertTrue("Array false",
- Boolean.FALSE.equals(it.next()));
- assertTrue("Array string true",
- "true".equals(it.next()));
- assertTrue("Array string false",
- "false".equals(it.next()));
- assertTrue("Array string",
- "hello".equals(it.next()));
-
- assertTrue("Array double [23.45e-4]",
- new BigDecimal("0.002345").equals(it.next()));
- assertTrue("Array string double",
- Double.valueOf(23.45).equals(Double.parseDouble((String)it.next())));
-
- assertTrue("Array value int",
- Integer.valueOf(42).equals(it.next()));
- assertTrue("Array value string int",
- Integer.valueOf(43).equals(Integer.parseInt((String)it.next())));
-
- JSONArray nestedJsonArray = (JSONArray)it.next();
- assertTrue("Array value JSONArray", nestedJsonArray != null);
-
- JSONObject nestedJsonObject = (JSONObject)it.next();
- assertTrue("Array value JSONObject", nestedJsonObject != null);
-
- assertTrue("Array value long",
- Long.valueOf(0).equals(((Number) it.next()).longValue()));
- assertTrue("Array value string long",
- Long.valueOf(-1).equals(Long.parseLong((String) it.next())));
- assertTrue("should be at end of array", !it.hasNext());
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- jsonArray, nestedJsonArray
- )));
- Util.checkJSONObjectMaps(nestedJsonObject);
- }
-
- @Test(expected = JSONPointerException.class)
- public void queryWithNoResult() {
- new JSONArray().query("/a/b");
- }
-
- @Test
- public void optQueryWithNoResult() {
- assertNull(new JSONArray().optQuery("/a/b"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void optQueryWithSyntaxError() {
- new JSONArray().optQuery("invalid");
- }
-
-
- /**
- * Exercise the JSONArray write() method
- */
- @Test
- public void write() throws IOException {
- String str = "[\"value1\",\"value2\",{\"key1\":1,\"key2\":2,\"key3\":3}]";
- JSONArray jsonArray = new JSONArray(str);
- String expectedStr = str;
- StringWriter stringWriter = new StringWriter();
- try {
- jsonArray.write(stringWriter);
- String actualStr = stringWriter.toString();
- JSONArray finalArray = new JSONArray(actualStr);
- Util.compareActualVsExpectedJsonArrays(jsonArray, finalArray);
- assertTrue("write() expected " + expectedStr +
- " but found " + actualStr,
- actualStr.startsWith("[\"value1\",\"value2\",{")
- && actualStr.contains("\"key1\":1")
- && actualStr.contains("\"key2\":2")
- && actualStr.contains("\"key3\":3")
- );
- } finally {
- stringWriter.close();
- }
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Exercise the JSONArray write() method using Appendable.
- */
-/*
- @Test
- public void writeAppendable() {
- String str = "[\"value1\",\"value2\",{\"key1\":1,\"key2\":2,\"key3\":3}]";
- JSONArray jsonArray = new JSONArray(str);
- String expectedStr = str;
- StringBuilder stringBuilder = new StringBuilder();
- Appendable appendable = jsonArray.write(stringBuilder);
- String actualStr = appendable.toString();
- assertTrue("write() expected " + expectedStr +
- " but found " + actualStr,
- expectedStr.equals(actualStr));
- }
-*/
-
- /**
- * Exercise the JSONArray write(Writer, int, int) method
- */
- @Test
- public void write3Param() throws IOException {
- String str0 = "[\"value1\",\"value2\",{\"key1\":1,\"key2\":false,\"key3\":3.14}]";
- JSONArray jsonArray = new JSONArray(str0);
- String expectedStr = str0;
- StringWriter stringWriter = new StringWriter();
- try {
- String actualStr = jsonArray.write(stringWriter, 0, 0).toString();
- JSONArray finalArray = new JSONArray(actualStr);
- Util.compareActualVsExpectedJsonArrays(jsonArray, finalArray);
- assertTrue("write() expected " + expectedStr +
- " but found " + actualStr,
- actualStr.startsWith("[\"value1\",\"value2\",{")
- && actualStr.contains("\"key1\":1")
- && actualStr.contains("\"key2\":false")
- && actualStr.contains("\"key3\":3.14")
- );
- } finally {
- stringWriter.close();
- }
-
- stringWriter = new StringWriter();
- try {
- String actualStr = jsonArray.write(stringWriter, 2, 1).toString();
- JSONArray finalArray = new JSONArray(actualStr);
- Util.compareActualVsExpectedJsonArrays(jsonArray, finalArray);
- assertTrue("write() expected " + expectedStr +
- " but found " + actualStr,
- actualStr.startsWith("[\n" +
- " \"value1\",\n" +
- " \"value2\",\n" +
- " {")
- && actualStr.contains("\"key1\": 1")
- && actualStr.contains("\"key2\": false")
- && actualStr.contains("\"key3\": 3.14")
- );
- Util.checkJSONArrayMaps(finalArray);
- } finally {
- stringWriter.close();
- }
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Exercise the JSONArray write(Appendable, int, int) method
- */
-/*
- @Test
- public void write3ParamAppendable() {
- String str0 = "[\"value1\",\"value2\",{\"key1\":1,\"key2\":false,\"key3\":3.14}]";
- String str2 =
- "[\n" +
- " \"value1\",\n" +
- " \"value2\",\n" +
- " {\n" +
- " \"key1\": 1,\n" +
- " \"key2\": false,\n" +
- " \"key3\": 3.14\n" +
- " }\n" +
- " ]";
- JSONArray jsonArray = new JSONArray(str0);
- String expectedStr = str0;
- StringBuilder stringBuilder = new StringBuilder();
- Appendable appendable = jsonArray.write(stringBuilder, 0, 0);
- String actualStr = appendable.toString();
- assertEquals(expectedStr, actualStr);
-
- expectedStr = str2;
- stringBuilder = new StringBuilder();
- appendable = jsonArray.write(stringBuilder, 2, 1);
- actualStr = appendable.toString();
- assertEquals(expectedStr, actualStr);
- }
-*/
-
- /**
- * Exercise JSONArray toString() method with various indent levels.
- */
- @Test
- public void toList() {
- String jsonArrayStr =
- "[" +
- "[1,2," +
- "{\"key3\":true}" +
- "]," +
- "{\"key1\":\"val1\",\"key2\":" +
- "{\"key2\":null}," +
- "\"key3\":42,\"key4\":[]" +
- "}," +
- "[" +
- "[\"value1\",2.1]" +
- "," +
- "[null]" +
- "]" +
- "]";
-
- JSONArray jsonArray = new JSONArray(jsonArrayStr);
- List> list = jsonArray.toList();
-
- assertTrue("List should not be null", list != null);
- assertTrue("List should have 3 elements", list.size() == 3);
-
- List> val1List = (List>) list.get(0);
- assertTrue("val1 should not be null", val1List != null);
- assertTrue("val1 should have 3 elements", val1List.size() == 3);
-
- assertTrue("val1 value 1 should be 1", val1List.get(0).equals(Integer.valueOf(1)));
- assertTrue("val1 value 2 should be 2", val1List.get(1).equals(Integer.valueOf(2)));
-
- Map,?> key1Value3Map = (Map,?>)val1List.get(2);
- assertTrue("Map should not be null", key1Value3Map != null);
- assertTrue("Map should have 1 element", key1Value3Map.size() == 1);
- assertTrue("Map key3 should be true", key1Value3Map.get("key3").equals(Boolean.TRUE));
-
- Map,?> val2Map = (Map,?>) list.get(1);
- assertTrue("val2 should not be null", val2Map != null);
- assertTrue("val2 should have 4 elements", val2Map.size() == 4);
- assertTrue("val2 map key 1 should be val1", val2Map.get("key1").equals("val1"));
- assertTrue("val2 map key 3 should be 42", val2Map.get("key3").equals(Integer.valueOf(42)));
-
- Map,?> val2Key2Map = (Map,?>)val2Map.get("key2");
- assertTrue("val2 map key 2 should not be null", val2Key2Map != null);
- assertTrue("val2 map key 2 should have an entry", val2Key2Map.containsKey("key2"));
- assertTrue("val2 map key 2 value should be null", val2Key2Map.get("key2") == null);
-
- List> val2Key4List = (List>)val2Map.get("key4");
- assertTrue("val2 map key 4 should not be null", val2Key4List != null);
- assertTrue("val2 map key 4 should be empty", val2Key4List.isEmpty());
-
- List> val3List = (List>) list.get(2);
- assertTrue("val3 should not be null", val3List != null);
- assertTrue("val3 should have 2 elements", val3List.size() == 2);
-
- List> val3Val1List = (List>)val3List.get(0);
- assertTrue("val3 list val 1 should not be null", val3Val1List != null);
- assertTrue("val3 list val 1 should have 2 elements", val3Val1List.size() == 2);
- assertTrue("val3 list val 1 list element 1 should be value1", val3Val1List.get(0).equals("value1"));
- assertTrue("val3 list val 1 list element 2 should be 2.1", val3Val1List.get(1).equals(new BigDecimal("2.1")));
-
- List> val3Val2List = (List>)val3List.get(1);
- assertTrue("val3 list val 2 should not be null", val3Val2List != null);
- assertTrue("val3 list val 2 should have 1 element", val3Val2List.size() == 1);
- assertTrue("val3 list val 2 list element 1 should be null", val3Val2List.get(0) == null);
-
- // assert that toList() is a deep copy
- jsonArray.getJSONObject(1).put("key1", "still val1");
- assertTrue("val2 map key 1 should be val1", val2Map.get("key1").equals("val1"));
-
- // assert that the new list is mutable
- assertTrue("Removing an entry should succeed", list.remove(2) != null);
- assertTrue("List should have 2 elements", list.size() == 2);
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Create a JSONArray with specified initial capacity.
- * Expects an exception if the initial capacity is specified as a negative integer
- */
- @Test
- public void testJSONArrayInt() {
- assertNotNull(new JSONArray(0));
- assertNotNull(new JSONArray(5));
- // Check Size -> Even though the capacity of the JSONArray can be specified using a positive
- // integer but the length of JSONArray always reflects upon the items added into it.
- // assertEquals(0l, new JSONArray(10).length());
- try {
- assertNotNull("Should throw an exception", new JSONArray(-1));
- } catch (JSONException e) {
- assertEquals("Expected an exception message",
- "JSONArray initial capacity cannot be negative.",
- e.getMessage());
- }
- }
-
- /**
- * Verifies that the object constructor can properly handle any supported collection object.
- */
- @Test
- @SuppressWarnings({ "unchecked", "boxing" })
- public void testObjectConstructor() {
- // should copy the array
- Object o = new Object[] {2, "test2", true};
- JSONArray a = new JSONArray(o);
- assertNotNull("Should not error", a);
- assertEquals("length", 3, a.length());
-
- // should NOT copy the collection
- // this is required for backwards compatibility
- o = new ArrayList();
- ((Collection)o).add(1);
- ((Collection)o).add("test");
- ((Collection)o).add(false);
- try {
- JSONArray a0 = new JSONArray(o);
- assertNull("Should error", a0);
- } catch (JSONException ex) {
- }
-
- // should NOT copy the JSONArray
- // this is required for backwards compatibility
- o = a;
- try {
- JSONArray a1 = new JSONArray(o);
- assertNull("Should error", a1);
- } catch (JSONException ex) {
- }
- Util.checkJSONArrayMaps(a);
- }
-
- /**
- * Verifies that the JSONArray constructor properly copies the original.
- */
- @Test
- public void testJSONArrayConstructor() {
- // should copy the array
- JSONArray a1 = new JSONArray("[2, \"test2\", true]");
- JSONArray a2 = new JSONArray(a1);
- assertNotNull("Should not error", a2);
- assertEquals("length", a1.length(), a2.length());
-
- for(int i = 0; i < a1.length(); i++) {
- assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
- }
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- a1, a2
- )));
- }
-
- /**
- * Verifies that the object constructor can properly handle any supported collection object.
- */
- @Test
- public void testJSONArrayPutAll() {
- // should copy the array
- JSONArray a1 = new JSONArray("[2, \"test2\", true]");
- JSONArray a2 = new JSONArray();
- a2.putAll(a1);
- assertNotNull("Should not error", a2);
- assertEquals("length", a1.length(), a2.length());
-
- for(int i = 0; i < a1.length(); i++) {
- assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
- }
- Util.checkJSONArraysMaps(new ArrayList(Arrays.asList(
- a1, a2
- )));
- }
-
- /**
- * Tests if calling JSONArray clear() method actually makes the JSONArray empty
- */
- @Test(expected = JSONException.class)
- public void jsonArrayClearMethodTest() {
- //Adds random stuff to the JSONArray
- JSONArray jsonArray = new JSONArray();
- jsonArray.put(123);
- jsonArray.put("456");
- jsonArray.put(new JSONArray());
- jsonArray.clear(); //Clears the JSONArray
- assertTrue("expected jsonArray.length() == 0", jsonArray.length() == 0); //Check if its length is 0
- jsonArray.getInt(0); //Should throws org.json.JSONException: JSONArray[0] not found
- Util.checkJSONArrayMaps(jsonArray);
- }
-
- /**
- * Tests for stack overflow. See https://github.com/stleary/JSON-java/issues/654
- */
- @Ignore("This test relies on system constraints and may not always pass. See: https://github.com/stleary/JSON-java/issues/821")
- @Test(expected = JSONException.class)
- public void issue654StackOverflowInputWellFormed() {
- //String input = new String(java.util.Base64.getDecoder().decode(base64Bytes));
- final InputStream resourceAsStream = JSONArrayTest.class.getClassLoader().getResourceAsStream("Issue654WellFormedArray.json");
- JSONTokener tokener = new JSONTokener(resourceAsStream);
- JSONArray json_input = new JSONArray(tokener);
- assertNotNull(json_input);
- fail("Excepected Exception due to stack overflow.");
- Util.checkJSONArrayMaps(json_input);
- }
-
- @Test
- public void testIssue682SimilarityOfJSONString() {
- JSONArray ja1 = new JSONArray()
- .put(new MyJsonString())
- .put(2);
- JSONArray ja2 = new JSONArray()
- .put(new MyJsonString())
- .put(2);
- assertTrue(ja1.similar(ja2));
-
- JSONArray ja3 = new JSONArray()
- .put(new JSONString() {
- @Override
- public String toJSONString() {
- return "\"different value\"";
- }
- })
- .put(2);
- assertFalse(ja1.similar(ja3));
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepth() {
- HashMap map = new HashMap<>();
- map.put("t", map);
- new JSONArray().put(map);
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepthAtPosition() {
- HashMap map = new HashMap<>();
- map.put("t", map);
- new JSONArray().put(0, map);
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepthArray() {
- ArrayList array = new ArrayList<>();
- array.add(array);
- new JSONArray(array);
- }
-
- @Test
- public void testRecursiveDepthAtPositionDefaultObject() {
- HashMap map = JSONObjectTest.buildNestedMap(ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
- new JSONArray().put(0, map);
- }
-
- @Test
- public void testRecursiveDepthAtPosition1000Object() {
- HashMap map = JSONObjectTest.buildNestedMap(1000);
- new JSONArray().put(0, map, new JSONParserConfiguration().withMaxNestingDepth(1000));
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepthAtPosition1001Object() {
- HashMap map = JSONObjectTest.buildNestedMap(1001);
- new JSONArray().put(0, map);
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepthArrayLimitedMaps() {
- ArrayList array = new ArrayList<>();
- array.add(array);
- new JSONArray(array);
- }
-
- @Test
- public void testRecursiveDepthArrayForDefaultLevels() {
- ArrayList array = buildNestedArray(ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
- new JSONArray(array, new JSONParserConfiguration());
- }
-
- @Test
- public void testRecursiveDepthArrayFor1000Levels() {
- try {
- ArrayList array = buildNestedArray(1000);
- JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withMaxNestingDepth(1000);
- new JSONArray(array, parserConfiguration);
- } catch (StackOverflowError e) {
- String javaVersion = System.getProperty("java.version");
- if (javaVersion.startsWith("11.")) {
- System.out.println(
- "testRecursiveDepthArrayFor1000Levels() allowing intermittent stackoverflow, Java Version: "
- + javaVersion);
- } else {
- String errorStr = "testRecursiveDepthArrayFor1000Levels() unexpected stackoverflow, Java Version: "
- + javaVersion;
- System.out.println(errorStr);
- throw new RuntimeException(errorStr);
- }
- }
- }
-
- @Test(expected = JSONException.class)
- public void testRecursiveDepthArrayFor1001Levels() {
- ArrayList array = buildNestedArray(1001);
- new JSONArray(array);
- }
-
- @Test
- public void testStrictModeJSONTokener_expectException(){
- JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode();
- JSONTokener tokener = new JSONTokener("[\"value\"]invalidCharacters", jsonParserConfiguration);
-
- assertThrows(JSONException.class, () -> { new JSONArray(tokener); });
- }
-
- public static ArrayList buildNestedArray(int maxDepth) {
- if (maxDepth <= 0) {
- return new ArrayList<>();
- }
- ArrayList nestedArray = new ArrayList<>();
- nestedArray.add(buildNestedArray(maxDepth - 1));
- return nestedArray;
- }
-}
diff --git a/src/test/java/org/json/junit/JSONMLTest.java b/src/test/java/org/json/junit/JSONMLTest.java
deleted file mode 100644
index 5a360dd59..000000000
--- a/src/test/java/org/json/junit/JSONMLTest.java
+++ /dev/null
@@ -1,989 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-
-import org.json.*;
-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 a JSONArray or JSONObject into an XML string.
- * Both fromstring and tostring operations operations should be symmetrical
- * 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 {
-
- /**
- * Attempts to transform a null XML string to JSON.
- * Expects a NullPointerException
- */
- @Test(expected=NullPointerException.class)
- public void nullXMLException() {
- String xmlStr = null;
- JSONML.toJSONArray(xmlStr);
- }
-
- /**
- * Attempts to transform an empty string to JSON.
- * Expects a JSONException
- */
- @Test
- public void emptyXMLException() {
- String xmlStr = "";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Bad XML at 0 [character 1 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempts to call JSONML.toString() with a null JSONArray.
- * Expects a NullPointerException.
- */
- @Test(expected=NullPointerException.class)
- public void nullJSONXMLException() {
- /**
- * Tries to convert a null JSONArray to XML.
- */
- JSONArray jsonArray= null;
- JSONML.toString(jsonArray);
- }
-
- /**
- * Attempts to call JSONML.toString() with a null JSONArray.
- * Expects a JSONException.
- */
- @Test
- public void emptyJSONXMLException() {
- /**
- * Tries to convert an empty JSONArray to XML.
- */
- JSONArray jsonArray = new JSONArray();
- try {
- JSONML.toString(jsonArray);
- assertTrue("Expecting an exception", false);
- } catch (JSONException e) {
- assertTrue("Expecting an exception message",
- "JSONArray[0] not found.".
- equals(e.getMessage()));
- }
- }
-
- /**
- * Attempts to transform an non-XML string to JSON.
- * Expects a JSONException
- */
- @Test
- public void nonXMLException() {
- /**
- * Attempts to transform a nonXML string to JSON
- */
- String xmlStr = "{ \"this is\": \"not xml\"}";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Bad XML at 23 [character 24 line 1]",
- e.getMessage());
- }
- }
-
- /**
- * Attempts to transform a JSON document with XML content that
- * does not follow JSONML conventions (element name is not first value
- * in a nested JSONArray) to a JSONArray then back to string.
- * Expects a JSONException
- */
- @Test
- public void emptyTagException() {
- /**
- * jsonArrayStr is used to build a JSONArray which is then
- * turned into XML. For this transformation, all arrays represent
- * elements and the first array entry is the name of the element.
- * In this case, one of the arrays does not have a name
- */
- String jsonArrayStr =
- "[\"addresses\","+
- "{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
- "\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
- // this array has no name
- "["+
- "[\"name\"],"+
- "[\"nocontent\"],"+
- "\">\""+
- "]"+
- "]";
- JSONArray jsonArray = new JSONArray(jsonArrayStr);
- try {
- JSONML.toString(jsonArray);
- assertTrue("Expecting an exception", false);
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONArray[0] is not a String (class org.json.JSONArray).",
- e.getMessage());
- }
- }
-
- /**
- * Attempts to transform a JSON document with XML content that
- * does not follow JSONML conventions (element tag has an embedded space)
- * to a JSONArray then back to string. Expects a JSONException
- */
- @Test
- public void spaceInTagException() {
- /**
- * jsonArrayStr is used to build a JSONArray which is then
- * turned into XML. For this transformation, all arrays represent
- * elements and the first array entry is the name of the element.
- * In this case, one of the element names has an embedded space,
- * which is not allowed.
- */
- String jsonArrayStr =
- "[\"addresses\","+
- "{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
- "\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
- // this array has an invalid name
- "[\"addr esses\","+
- "[\"name\"],"+
- "[\"nocontent\"],"+
- "\">\""+
- "]"+
- "]";
- JSONArray jsonArray = new JSONArray(jsonArrayStr);
- try {
- JSONML.toString(jsonArray);
- assertTrue("Expecting an exception", false);
- } catch (JSONException e) {
- assertTrue("Expecting an exception message",
- "'addr esses' contains a space character.".
- equals(e.getMessage()));
- }
- }
-
- /**
- * Attempts to transform a malformed XML document
- * (element tag has a frontslash) to a JSONArray.\
- * Expects a JSONException
- */
- @Test
- public void invalidSlashInTagException() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * In this case, the XML is invalid because the 'name' element
- * contains an invalid frontslash.
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " abc street \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Misshaped tag at 176 [character 14 line 4]",
- e.getMessage());
- }
- }
-
- /**
- * Malformed XML text (invalid tagname) is transformed into a JSONArray.
- * Expects a JSONException.
- */
- @Test
- public void invalidBangInTagException() {
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Misshaped meta tag at 215 [character 12 line 7]",
- e.getMessage());
- }
- }
-
- /**
- * Malformed XML text (invalid tagname, no close bracket) is transformed\
- * into a JSONArray. Expects a JSONException.
- */
- @Test
- public void invalidBangNoCloseInTagException() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * In this case, the XML is invalid because an element
- * starts with '!' and has no closing tag
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Misshaped meta tag at 214 [character 12 line 7]",
- e.getMessage());
- }
- }
-
- /**
- * Malformed XML text (tagname with no close bracket) is transformed\
- * into a JSONArray. Expects a JSONException.
- */
- @Test
- public void noCloseStartTagException() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * In this case, the XML is invalid because an element
- * has no closing '>'.
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Misplaced '<' at 194 [character 5 line 6]",
- e.getMessage());
- }
- }
-
- /**
- * Malformed XML text (endtag with no name) is transformed\
- * into a JSONArray. Expects a JSONException.
- */
- @Test
- public void noCloseEndTagException() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * In this case, the XML is invalid because an element
- * has no name after the closing tag ''.
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " \n"+
- " >\n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- assertTrue("Expecting an exception", false);
- } catch (JSONException e) {
- assertTrue("Expecting an exception message",
- "Expected a closing name instead of '>'.".
- equals(e.getMessage()));
- }
- }
-
- /**
- * Malformed XML text (endtag with no close bracket) is transformed\
- * into a JSONArray. Expects a JSONException.
- */
- @Test
- public void noCloseEndBraceException() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * In this case, the XML is invalid because an element
- * has '>' after the closing tag '' and name.
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Misplaced '<' at 206 [character 1 line 7]",
- e.getMessage());
- }
- }
-
- /**
- * Malformed XML text (incomplete CDATA string) is transformed\
- * into a JSONArray. Expects a JSONException.
- */
- @Test
- public void invalidCDATABangInTagException() {
- /**
- * 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.
- */
- String xmlStr =
- "\n"+
- "\n"+
- " \n"+
- " Joe Tester \n"+
- " \n"+
- " \n"+
- " ";
- try {
- JSONML.toJSONArray(xmlStr);
- fail("Expecting an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Expected 'CDATA[' at 204 [character 11 line 5]",
- e.getMessage());
- }
- }
-
- /**
- * 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
- * confirm the contents.
- */
- @Test
- public void toJSONArray() {
- /**
- * xmlStr contains XML text which is transformed into a JSONArray.
- * Each element becomes a JSONArray:
- * 1st entry = elementname
- * 2nd entry = attributes object (if present)
- * 3rd entry = content (if present)
- * 4th entry = child element JSONArrays (if present)
- * The result is compared against an expected JSONArray.
- * The transformed JSONArray is then transformed back into a string
- * which is used to create a final JSONArray, which is also compared
- * against the expected JSONArray.
- */
- String xmlStr =
- "\n"+
- "\n"+
- "\n"+
- "myName \n"+
- " >\n"+
- " \n"+
- " ";
- String expectedStr =
- "[\"addresses\","+
- "{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
- "\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
- "[\"address\","+
- "{\"attr1\":\"attrValue1\",\"attr2\":\"attrValue2\",\"attr3\":\"attrValue3\"},"+
- "[\"name\", {\"nameType\":\"mine\"},\"myName\"],"+
- "[\"nocontent\"],"+
- "\">\""+
- "]"+
- "]";
- JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
- JSONArray expectedJsonArray = new JSONArray(expectedStr);
- String xmlToStr = JSONML.toString(jsonArray);
- JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
- }
-
- /**
- * 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.
- *
- * 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.
- *
- * This test gives a comprehensive example of how the JSONML
- * transformations work.
- */
- @Test
- public void toJSONObjectToJSONArray() {
- /**
- * 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
- * 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 =
- "\n"+
- "\n"+
- "\n"+
- "Joe Tester \n"+
- " \n"+
- " \n"+
- "true \n"+
- "false \n"+
- "null \n"+
- "42 \n"+
- "-23 \n"+
- "-23.45 \n"+
- "-23x.45 \n"+
- "\n"+
- "1 \n"+
- "2 \n"+
- "abc \n"+
- "3 \n"+
- "4.1 \n"+
- "5.2 \n"+
- " \n"+
- " \n"+
- " ";
-
- String expectedJSONObjectStr =
- "{"+
- "\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
- "\"childNodes\":["+
- "{"+
- "\"childNodes\":["+
- "{"+
- "\"childNodes\":[\"Joe Tester\"],"+
- "\"nameType\":\"my name\","+
- "\"tagName\":\"name\""+
- "},"+
- "{"+
- "\"childNodes\":[\"Baker street 5\"],"+
- "\"tagName\":\"street\""+
- "},"+
- "{"+
- "\"tagName\":\"NothingHere\","+
- "\"except\":\"an attribute\""+
- "},"+
- "{"+
- "\"childNodes\":[true],"+
- "\"tagName\":\"TrueValue\""+
- "},"+
- "{"+
- "\"childNodes\":[false],"+
- "\"tagName\":\"FalseValue\""+
- "},"+
- "{"+
- "\"childNodes\":[null],"+
- "\"tagName\":\"NullValue\""+
- "},"+
- "{"+
- "\"childNodes\":[42],"+
- "\"tagName\":\"PositiveValue\""+
- "},"+
- "{"+
- "\"childNodes\":[-23],"+
- "\"tagName\":\"NegativeValue\""+
- "},"+
- "{"+
- "\"childNodes\":[-23.45],"+
- "\"tagName\":\"DoubleValue\""+
- "},"+
- "{"+
- "\"childNodes\":[\"-23x.45\"],"+
- "\"tagName\":\"Nan\""+
- "},"+
- "{"+
- "\"childNodes\":["+
- "{"+
- "\"childNodes\":[1],"+
- "\"tagName\":\"value\""+
- "},"+
- "{"+
- "\"childNodes\":[2],"+
- "\"tagName\":\"value\""+
- "},"+
- "{"+
- "\"childNodes\":["+
- "{"+
- "\"childNodes\":[\"abc\"],"+
- "\"svAttr\":\"svValue\","+
- "\"tagName\":\"subValue\""+
- "}"+
- "],"+
- "\"tagName\":\"value\""+
- "},"+
- "{"+
- "\"childNodes\":[3],"+
- "\"tagName\":\"value\""+
- "},"+
- "{"+
- "\"childNodes\":[4.1],"+
- "\"tagName\":\"value\""+
- "},"+
- "{"+
- "\"childNodes\":[5.2],"+
- "\"tagName\":\"value\""+
- "}"+
- "],"+
- "\"tagName\":\"ArrayOfNum\""+
- "}"+
- "],"+
- "\"addrType\":\"my address\","+
- "\"tagName\":\"address\""+
- "}"+
- "],"+
- "\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\","+
- "\"tagName\":\"addresses\""+
- "}";
-
- String expectedJSONArrayStr =
- "["+
- "\"addresses\","+
- "{"+
- "\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
- "\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\""+
- "},"+
- "["+
- "\"address\","+
- "{"+
- "\"addrType\":\"my address\""+
- "},"+
- "["+
- "\"name\","+
- "{"+
- "\"nameType\":\"my name\""+
- "},"+
- "\"Joe Tester\""+
- "],"+
- "[\"street\",\"Baker street 5\"],"+
- "["+
- "\"NothingHere\","+
- "{\"except\":\"an attribute\"}"+
- "],"+
- "[\"TrueValue\",true],"+
- "[\"FalseValue\",false],"+
- "[\"NullValue\",null],"+
- "[\"PositiveValue\",42],"+
- "[\"NegativeValue\",-23],"+
- "[\"DoubleValue\",-23.45],"+
- "[\"Nan\",\"-23x.45\"],"+
- "["+
- "\"ArrayOfNum\","+
- "[\"value\",1],"+
- "[\"value\",2],"+
- "[\"value\","+
- "["+
- "\"subValue\","+
- "{\"svAttr\":\"svValue\"},"+
- "\"abc\""+
- "]"+
- "],"+
- "[\"value\",3],"+
- "[\"value\",4.1],"+
- "[\"value\",5.2]"+
- "]"+
- "]"+
- "]";
-
- // make a JSONObject and make sure it looks as expected
- JSONObject jsonObject = JSONML.toJSONObject(xmlStr);
- JSONObject expectedJsonObject = new JSONObject(expectedJSONObjectStr);
- Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
-
- // restore the XML, then make another JSONObject and make sure it
- // looks as expected
- String jsonObjectXmlToStr = JSONML.toString(jsonObject);
- JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
- Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
-
- // 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);
- JSONArray finalJsonArray = JSONML.toJSONArray(jsonArrayXmlToStr);
- Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
-
- // lastly, confirm the restored JSONObject XML and JSONArray XML look
- // reasonably similar
- JSONObject jsonObjectFromObject = JSONML.toJSONObject(jsonObjectXmlToStr);
- JSONObject jsonObjectFromArray = JSONML.toJSONObject(jsonArrayXmlToStr);
- Util.compareActualVsExpectedJsonObjects(jsonObjectFromObject, jsonObjectFromArray);
- }
-
- /**
- * 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.
- *
- * This test shows how XML comments are handled.
- */
- @Test
- public void commentsInXML() {
-
- String xmlStr =
- "\n"+
- "\n"+
- "\n"+
- "\n"+
- "\n"+
- "Joe Tester \n"+
- "\n"+
- "Baker street 5 \n"+
- " \n"+
- " ";
- String expectedStr =
- "[\"addresses\","+
- "[\"address\","+
- "[\"name\",\"Joe Tester\"],"+
- "[\"street\",\"Baker street 5\"]"+
- "]"+
- "]";
- JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
- JSONArray expectedJsonArray = new JSONArray(expectedStr);
- String xmlToStr = JSONML.toString(jsonArray);
- JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
- Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
- Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
- }
-
- /**
- * JSON string with lost leading zero and converted "True" to true. See test
- * result in comment below.
- */
- @Test
- public void testToJSONArray_jsonOutput() {
- final String originalXml = "01 1 00 0 True ";
- final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",1],[\"id\",\"00\"],[\"id\",0],[\"item\",{\"id\":\"01\"}],[\"title\",true]]";
- final JSONArray actualJsonOutput = JSONML.toJSONArray(originalXml, false);
- assertEquals(expectedJsonString, actualJsonOutput.toString());
- }
-
- /**
- * JSON string cannot be reverted to original xml when type guessing is used.
- */
- @Test
- public void testToJSONArray_reversibility() {
- final String originalXml = "01 1 00 0 True ";
- final String revertedXml = JSONML.toString(JSONML.toJSONArray(originalXml, false));
- assertNotEquals(revertedXml, originalXml);
- }
-
- /**
- * JSON string cannot be reverted to original xml when type guessing is used.
- * When we force all the values as string, the original text comes back.
- */
- @Test
- public void testToJSONArray_reversibility2() {
- final String originalXml = "01 1 00 0 True ";
- 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);
- }
-
- /**
- * JSON can be reverted to original xml.
- */
- @Test
- public void testToJSONArray_reversibility3() {
- final String originalXml = "400402 ";
- final JSONArray jsonArray = JSONML.toJSONArray(originalXml, false);
- final String revertedXml = JSONML.toString(jsonArray);
- assertEquals(revertedXml, originalXml);
- }
-
- /**
- * JSON string cannot be reverted to original xml. See test result in
- * comment below.
- */
- @Test
- public void testToJSONObject_reversibility() {
- final String originalXml = "400402 ";
- final JSONObject originalObject=JSONML.toJSONObject(originalXml,false);
- final String originalJson = originalObject.toString();
- final String xml = JSONML.toString(originalObject);
- final JSONObject revertedObject = JSONML.toJSONObject(xml, false);
- final String newJson = revertedObject.toString();
- assertTrue("JSON Objects are not similar", originalObject.similar(revertedObject));
- assertTrue("JSON Strings are not similar", new JSONObject(originalJson).similar(new JSONObject(newJson)));
- }
-
-// these tests do not pass for the following reasons:
-// 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 can not be reversed reliably.
-//
-// /**
-// * Test texts taken from jsonml.org. Currently our implementation FAILS this conversion but shouldn't.
-// * Technically JsonML should be able to transform any valid xhtml document, but ours only supports
-// * standard XML entities, not HTML entities.
-// */
-// @Test
-// public void testAttributeConversionReversabilityHTML() {
-// final String originalXml = "
#5D28D1 Example text here #AF44EF 127310656 #AAD034 ©
";
-// 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.
-// */
-// @Test
-// public void testAttributeConversionReversabilityXML() {
-// final String originalXml = "#5D28D1 Example text here #AF44EF 127310656 #AAD034 &> <
";
-// 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
-// assertEquals(originalXml, reverseXml);
-//
-// assertEquals(expectedJsonString, actualJsonString);
-// }
-
- @Test (timeout = 6000)
- public void testIssue484InfinteLoop1() {
- try {
- JSONML.toJSONObject("??*^M??|?CglR^F??`??>?w??PIlr^E??D^X^]?$?-^R?o??O?*??{OD?^FY??`2a????NM?b^Tq?:O?>S$^K?J?^FB.gUK?m^H??zE??^??!v]?^A???^[^A??^U?c??????h???s???g^Z???`?q^Dbi??:^QZl?)?}1^??k?0??:$V?$?Ovs(}J??^V????2;^QgQ?^_^A?^D?^U?Tg?K?`?h%c?hmGA??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?");
-
- 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 = "\n" +
- " \n" +
- " sonoo \n" +
- " 56000 \n" +
- " true \n" +
- " \n" +
- " \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 = "\n" +
- " \n" +
- " sonoo \n" +
- " 56000 \n" +
- " true \n" +
- " \n" +
- " \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", "");
-
- 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", " ") +
- "value" +
- new String(new char[actualDepth]).replace("\0", " ");
-
- 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", "");
-
- 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 = "\n" +
- " \n" +
- " sonoo \n" +
- " 56000 \n" +
- " true \n" +
- " \n" +
- " \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 = "\n" +
- " \n" +
- " sonoo \n" +
- " 56000 \n" +
- " true \n" +
- " \n" +
- " \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");
- }
- }
-
-}
diff --git a/src/test/java/org/json/junit/JSONObjectLocaleTest.java b/src/test/java/org/json/junit/JSONObjectLocaleTest.java
deleted file mode 100755
index 1cdaf743d..000000000
--- a/src/test/java/org/json/junit/JSONObjectLocaleTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.json.junit;
-
-/*
-Public Domain.
-*/
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.json.*;
-import org.json.junit.data.MyLocaleBean;
-import org.junit.*;
-
-/**
- * Note: This file is saved as UTF-8. Do not save as ASCII or the tests will
- * fail.
- *
- */
-public class JSONObjectLocaleTest {
- /**
- * JSONObject built from a bean with locale-specific keys.
- * In the Turkish alphabet, there are 2 versions of the letter "i".
- * 'eh' I ı (dotless i)
- * 'ee' İ i (dotted i)
- * A problem can occur when parsing the public get methods for a bean.
- * If the method starts with getI... then the key name will be lowercased
- * to 'i' in English, and 'ı' in Turkish.
- * We want the keys to be consistent regardless of locale, so JSON-Java
- * lowercase operations are made to be locale-neutral by specifying
- * Locale.ROOT. This causes 'I' to be universally lowercased to 'i'
- * regardless of the locale currently in effect.
- */
- @Test
- public void jsonObjectByLocaleBean() {
-
- MyLocaleBean myLocaleBean = new MyLocaleBean();
-
- /**
- * This is just the control case which happens when the locale.ROOT
- * lowercasing behavior is the same as the current locale.
- */
- Locale.setDefault(new Locale("en"));
- JSONObject jsonen = new JSONObject(myLocaleBean);
- assertEquals("expected size 2, found: " +jsonen.length(), 2, jsonen.length());
- assertEquals("expected jsonen[i] == beanI", "beanI", jsonen.getString("i"));
- assertEquals("expected jsonen[id] == beanId", "beanId", jsonen.getString("id"));
-
- /**
- * Without the JSON-Java change, these keys would be stored internally as
- * starting with the letter, 'ı' (dotless i), since the lowercasing of
- * the getI and getId keys would be specific to the Turkish locale.
- */
- Locale.setDefault(new Locale("tr"));
- JSONObject jsontr = new JSONObject(myLocaleBean);
- assertEquals("expected size 2, found: " +jsontr.length(), 2, jsontr.length());
- assertEquals("expected jsontr[i] == beanI", "beanI", jsontr.getString("i"));
- assertEquals("expected jsontr[id] == beanId", "beanId", jsontr.getString("id"));
- }
-}
diff --git a/src/test/java/org/json/junit/JSONObjectNumberTest.java b/src/test/java/org/json/junit/JSONObjectNumberTest.java
deleted file mode 100644
index 0f2af2902..000000000
--- a/src/test/java/org/json/junit/JSONObjectNumberTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-package org.json.junit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Collection;
-
-import org.json.JSONObject;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(value = Parameterized.class)
-public class JSONObjectNumberTest {
- private final String objectString;
- private Integer value = 50;
-
- @Parameters(name = "{index}: {0}")
- public static Collection data() {
- return Arrays.asList(new Object[][]{
- {"{\"value\":50}", 1},
- {"{\"value\":50.0}", 1},
- {"{\"value\":5e1}", 1},
- {"{\"value\":5E1}", 1},
- {"{\"value\":5e1}", 1},
- {"{\"value\":\"50\"}", 1},
- {"{\"value\":-50}", -1},
- {"{\"value\":-50.0}", -1},
- {"{\"value\":-5e1}", -1},
- {"{\"value\":-5E1}", -1},
- {"{\"value\":-5e1}", -1},
- {"{\"value\":\"-50\"}", -1}
- // JSON does not support octal or hex numbers;
- // see https://stackoverflow.com/a/52671839/6323312
- // "{value:062}", // octal 50
- // "{value:0x32}" // hex 50
- });
- }
-
- public JSONObjectNumberTest(String objectString, int resultIsNegative) {
- this.objectString = objectString;
- this.value *= resultIsNegative;
- }
-
- private JSONObject object;
-
- @Before
- public void setJsonObject() {
- object = new JSONObject(objectString);
- }
-
- @Test
- public void testGetNumber() {
- assertEquals(value.intValue(), object.getNumber("value").intValue());
- }
-
- @Test
- public void testGetBigDecimal() {
- assertTrue(BigDecimal.valueOf(value).compareTo(object.getBigDecimal("value")) == 0);
- }
-
- @Test
- public void testGetBigInteger() {
- assertEquals(BigInteger.valueOf(value), object.getBigInteger("value"));
- }
-
- @Test
- public void testGetFloat() {
- assertEquals(value.floatValue(), object.getFloat("value"), 0.0f);
- }
-
- @Test
- public void testGetDouble() {
- assertEquals(value.doubleValue(), object.getDouble("value"), 0.0d);
- }
-
- @Test
- public void testGetInt() {
- assertEquals(value.intValue(), object.getInt("value"));
- }
-
- @Test
- public void testGetLong() {
- assertEquals(value.longValue(), object.getLong("value"));
- }
-
- @Test
- public void testOptNumber() {
- assertEquals(value.intValue(), object.optNumber("value").intValue());
- }
-
- @Test
- public void testOptBigDecimal() {
- assertTrue(BigDecimal.valueOf(value).compareTo(object.optBigDecimal("value", null)) == 0);
- }
-
- @Test
- public void testOptBigInteger() {
- assertEquals(BigInteger.valueOf(value), object.optBigInteger("value", null));
- }
-
- @Test
- public void testOptFloat() {
- assertEquals(value.floatValue(), object.optFloat("value"), 0.0f);
- }
-
- @Test
- public void testOptFloatObject() {
- assertEquals((Float) value.floatValue(), object.optFloatObject("value"), 0.0f);
- }
-
- @Test
- public void testOptDouble() {
- assertEquals(value.doubleValue(), object.optDouble("value"), 0.0d);
- }
-
- @Test
- public void testOptDoubleObject() {
- assertEquals((Double) value.doubleValue(), object.optDoubleObject("value"), 0.0d);
- }
-
- @Test
- public void testOptInt() {
- assertEquals(value.intValue(), object.optInt("value"));
- }
-
- @Test
- public void testOptIntegerObject() {
- assertEquals((Integer) value.intValue(), object.optIntegerObject("value"));
- }
-
- @Test
- public void testOptLong() {
- assertEquals(value.longValue(), object.optLong("value"));
- }
-
- @Test
- public void testOptLongObject() {
- assertEquals((Long) value.longValue(), object.optLongObject("value"));
- }
-}
diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java
deleted file mode 100644
index 061f18594..000000000
--- a/src/test/java/org/json/junit/JSONObjectTest.java
+++ /dev/null
@@ -1,4047 +0,0 @@
-package org.json.junit;
-
-/*
-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.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.regex.Pattern;
-
-import org.json.CDL;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONPointerException;
-import org.json.JSONParserConfiguration;
-import org.json.JSONString;
-import org.json.JSONTokener;
-import org.json.ParserConfiguration;
-import org.json.XML;
-import org.json.junit.data.BrokenToString;
-import org.json.junit.data.ExceptionalBean;
-import org.json.junit.data.Fraction;
-import org.json.junit.data.GenericBean;
-import org.json.junit.data.GenericBeanInt;
-import org.json.junit.data.MyBean;
-import org.json.junit.data.MyBeanCustomName;
-import org.json.junit.data.MyBeanCustomNameSubClass;
-import org.json.junit.data.MyBigNumberBean;
-import org.json.junit.data.MyEnum;
-import org.json.junit.data.MyEnumField;
-import org.json.junit.data.MyJsonString;
-import org.json.junit.data.MyNumber;
-import org.json.junit.data.MyNumberContainer;
-import org.json.junit.data.MyPublicClass;
-import org.json.junit.data.RecursiveBean;
-import org.json.junit.data.RecursiveBeanEquals;
-import org.json.junit.data.Singleton;
-import org.json.junit.data.SingletonEnum;
-import org.json.junit.data.WeirdList;
-import org.junit.After;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.JsonPath;
-
-/**
- * JSONObject, along with JSONArray, are the central classes of the reference app.
- * All of the other classes interact with them, and JSON functionality would
- * otherwise be impossible.
- */
-public class JSONObjectTest {
-
- /**
- * Regular Expression Pattern that matches JSON Numbers. This is primarily used for
- * output to guarantee that we are always writing valid JSON.
- */
- static final Pattern NUMBER_PATTERN = Pattern.compile("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?");
-
- @After
- public void tearDown() {
- SingletonEnum.getInstance().setSomeInt(0);
- SingletonEnum.getInstance().setSomeString(null);
- Singleton.getInstance().setSomeInt(0);
- Singleton.getInstance().setSomeString(null);
- }
-
- /**
- * Tests that the similar method is working as expected.
- */
- @Test
- public void verifySimilar() {
- final String string1 = "HasSameRef";
- final String string2 = "HasDifferentRef";
- JSONObject obj1 = new JSONObject()
- .put("key1", "abc")
- .put("key2", 2)
- .put("key3", string1);
-
- JSONObject obj2 = new JSONObject()
- .put("key1", "abc")
- .put("key2", 3)
- .put("key3", string1);
-
- JSONObject obj3 = new JSONObject()
- .put("key1", "abc")
- .put("key2", 2)
- .put("key3", new String(string1));
-
- JSONObject obj4 = new JSONObject()
- .put("key1", "abc")
- .put("key2", 2.0)
- .put("key3", new String(string1));
-
- JSONObject obj5 = new JSONObject()
- .put("key1", "abc")
- .put("key2", 2.0)
- .put("key3", new String(string2));
-
- assertFalse("obj1-obj2 Should eval to false", obj1.similar(obj2));
- assertTrue("obj1-obj3 Should eval to true", obj1.similar(obj3));
- assertTrue("obj1-obj4 Should eval to true", obj1.similar(obj4));
- assertFalse("obj1-obj5 Should eval to false", obj1.similar(obj5));
- // verify that a double and big decimal are "similar"
- assertTrue("should eval to true",new JSONObject().put("a",1.1d).similar(new JSONObject("{\"a\":1.1}")));
- // Confirm #618 is fixed (compare should not exit early if similar numbers are found)
- // Note that this test may not work if the JSONObject map entry order changes
- JSONObject first = new JSONObject("{\"a\": 1, \"b\": 2, \"c\": 3}");
- JSONObject second = new JSONObject("{\"a\": 1, \"b\": 2.0, \"c\": 4}");
- assertFalse("first-second should eval to false", first.similar(second));
- List jsonObjects = new ArrayList(
- Arrays.asList(obj1, obj2, obj3, obj4, obj5)
- );
- Util.checkJSONObjectsMaps(jsonObjects);
- }
-
- @Test
- public void timeNumberParsing() {
- // test data to use
- final String[] testData = new String[] {
- null,
- "",
- "100",
- "-100",
- "abc123",
- "012345",
- "100.5e199",
- "-100.5e199",
- "DEADBEEF",
- "0xDEADBEEF",
- "1234567890.1234567890",
- "-1234567890.1234567890",
- "adloghakuidghauiehgauioehgdkjfb nsruoh aeu noerty384 nkljfgh "
- + "395h tdfn kdz8yt3 4hkls gn.ey85 4hzfhnz.o8y5a84 onvklt "
- + "yh389thub nkz8y49lihv al4itlaithknty8hnbl"
- // long (in length) number sequences with invalid data at the end of the
- // string offer very poor performance for the REGEX.
- ,"123467890123467890123467890123467890123467890123467890123467"
- + "8901234678901234678901234678901234678901234678901234678"
- + "9012346789012346789012346789012346789012346789012346789"
- + "0a"
- };
- final int testDataLength = testData.length;
- /**
- * Changed to 1000 for faster test runs
- */
- // final int iterations = 1000000;
- final int iterations = 1000;
-
- // 10 million iterations 1,000,000 * 10 (currently 100,000)
- long startTime = System.nanoTime();
- for(int i = 0; i < iterations; i++) {
- for(int j = 0; j < testDataLength; j++) {
- try {
- BigDecimal v1 = new BigDecimal(testData[j]);
- v1.signum();
- } catch(Exception ignore) {
- //do nothing
- }
- }
- }
- final long elapsedNano1 = System.nanoTime() - startTime;
- System.out.println("new BigDecimal(testData[]) : " + elapsedNano1 / 1000000 + " ms");
-
- startTime = System.nanoTime();
- for(int i = 0; i < iterations; i++) {
- for(int j = 0; j < testDataLength; j++) {
- try {
- boolean v2 = NUMBER_PATTERN.matcher(testData[j]).matches();
- assert v2 == !!v2;
- } catch(Exception ignore) {
- //do nothing
- }
- }
- }
- final long elapsedNano2 = System.nanoTime() - startTime;
- System.out.println("NUMBER_PATTERN.matcher(testData[]).matches() : " + elapsedNano2 / 1000000 + " ms");
- // don't assert normally as the testing is machine dependent.
- // assertTrue("Expected Pattern matching to be faster than BigDecimal constructor",elapsedNano2)(JsonPath.read(doc, "$"))).size() == 4);
- assertTrue("expected \"falseKey\":false", Boolean.FALSE.equals(jsonObjectByName.query("/falseKey")));
- assertTrue("expected \"nullKey\":null", JSONObject.NULL.equals(jsonObjectByName.query("/nullKey")));
- assertTrue("expected \"stringKey\":\"hello world!\"", "hello world!".equals(jsonObjectByName.query("/stringKey")));
- assertTrue("expected \"doubleKey\":-23.45e67", new BigDecimal("-23.45e67").equals(jsonObjectByName.query("/doubleKey")));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(jsonObject, jsonObjectByName)));
- }
-
- /**
- * JSONObjects can be built from a Map.
- * In this test the map is null.
- * the JSONObject(JsonTokener) ctor is not tested directly since it already
- * has full coverage from other tests.
- */
- @Test
- public void jsonObjectByNullMap() {
- Map map = null;
- JSONObject jsonObject = new JSONObject(map);
- assertTrue("jsonObject should be empty", jsonObject.isEmpty());
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * JSONObjects can be built from a Map.
- * In this test all of the map entries are valid JSON types.
- */
- @Test
- public void jsonObjectByMap() {
- Map map = new HashMap();
- map.put("trueKey", Boolean.valueOf(true));
- map.put("falseKey", Boolean.valueOf(false));
- map.put("stringKey", "hello world!");
- map.put("escapeStringKey", "h\be\tllo w\u1234orld!");
- map.put("intKey", Long.valueOf(42));
- map.put("doubleKey", Double.valueOf(-23.45e67));
- JSONObject jsonObject = new JSONObject(map);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected \"trueKey\":true", Boolean.TRUE.equals(jsonObject.query("/trueKey")));
- assertTrue("expected \"falseKey\":false", Boolean.FALSE.equals(jsonObject.query("/falseKey")));
- assertTrue("expected \"stringKey\":\"hello world!\"", "hello world!".equals(jsonObject.query("/stringKey")));
- assertTrue("expected \"escapeStringKey\":\"h\be\tllo w\u1234orld!\"", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/escapeStringKey")));
- assertTrue("expected \"doubleKey\":-23.45e67", Double.valueOf("-23.45e67").equals(jsonObject.query("/doubleKey")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Verifies that the constructor has backwards compatability with RAW types pre-java5.
- */
- @Test
- public void verifyConstructor() {
-
- final JSONObject expected = new JSONObject("{\"myKey\":10}");
-
- @SuppressWarnings("rawtypes")
- Map myRawC = Collections.singletonMap("myKey", Integer.valueOf(10));
- JSONObject jaRaw = new JSONObject(myRawC);
-
- Map myCStrObj = Collections.singletonMap("myKey",
- (Object) Integer.valueOf(10));
- JSONObject jaStrObj = new JSONObject(myCStrObj);
-
- Map myCStrInt = Collections.singletonMap("myKey",
- Integer.valueOf(10));
- JSONObject jaStrInt = new JSONObject(myCStrInt);
-
- Map, ?> myCObjObj = Collections.singletonMap((Object) "myKey",
- (Object) Integer.valueOf(10));
- JSONObject jaObjObj = new JSONObject(myCObjObj);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrObj));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrInt));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObjObj));
- Util.checkJSONObjectsMaps(new ArrayList(
- Arrays.asList(jaRaw, jaStrObj, jaStrInt, jaObjObj))
- );
- }
-
- /**
- * Tests Number serialization.
- */
- @Test
- public void verifyNumberOutput(){
- /**
- * MyNumberContainer is a POJO, so call JSONObject(bean),
- * which builds a map of getter names/values
- * The only getter is getMyNumber (key=myNumber),
- * whose return value is MyNumber. MyNumber extends Number,
- * but is not recognized as such by wrap() per current
- * implementation, so wrap() returns the default new JSONObject(bean).
- * The only getter is getNumber (key=number), whose return value is
- * BigDecimal(42).
- */
- JSONObject jsonObject0 = new JSONObject(new MyNumberContainer());
- String actual = jsonObject0.toString();
- String expected = "{\"myNumber\":{\"number\":42}}";
- assertEquals("Equal", expected , actual);
-
- /**
- * JSONObject.put() handles objects differently than the
- * bean constructor. Where the bean ctor wraps objects before
- * placing them in the map, put() inserts the object without wrapping.
- * In this case, a MyNumber instance is the value.
- * The MyNumber.toString() method is responsible for
- * returning a reasonable value: the string '42'.
- */
- JSONObject jsonObject1 = new JSONObject();
- jsonObject1.put("myNumber", new MyNumber());
- actual = jsonObject1.toString();
- expected = "{\"myNumber\":42}";
- assertEquals("Equal", expected , actual);
-
- /**
- * Calls the JSONObject(Map) ctor, which calls wrap() for values.
- * AtomicInteger is a Number, but is not recognized by wrap(), per
- * current implementation. However, the type is
- * 'java.util.concurrent.atomic', so due to the 'java' prefix,
- * wrap() inserts the value as a string. That is why 42 comes back
- * wrapped in quotes.
- */
- JSONObject jsonObject2 = new JSONObject(Collections.singletonMap("myNumber", new AtomicInteger(42)));
- actual = jsonObject2.toString();
- expected = "{\"myNumber\":\"42\"}";
- assertEquals("Equal", expected , actual);
-
- /**
- * JSONObject.put() inserts the AtomicInteger directly into the
- * map not calling wrap(). In toString()->write()->writeValue(),
- * AtomicInteger is recognized as a Number, and converted via
- * numberToString() into the unquoted string '42'.
- */
- JSONObject jsonObject3 = new JSONObject();
- jsonObject3.put("myNumber", new AtomicInteger(42));
- actual = jsonObject3.toString();
- expected = "{\"myNumber\":42}";
- assertEquals("Equal", expected , actual);
-
- /**
- * Calls the JSONObject(Map) ctor, which calls wrap() for values.
- * Fraction is a Number, but is not recognized by wrap(), per
- * current implementation. As a POJO, Fraction is handled as a
- * bean and inserted into a contained JSONObject. It has 2 getters,
- * for numerator and denominator.
- */
- JSONObject jsonObject4 = new JSONObject(Collections.singletonMap("myNumber", new Fraction(4,2)));
- assertEquals(1, jsonObject4.length());
- assertEquals(2, ((JSONObject)(jsonObject4.get("myNumber"))).length());
- assertEquals("Numerator", BigInteger.valueOf(4) , jsonObject4.query("/myNumber/numerator"));
- assertEquals("Denominator", BigInteger.valueOf(2) , jsonObject4.query("/myNumber/denominator"));
-
- /**
- * JSONObject.put() inserts the Fraction directly into the
- * map not calling wrap(). In toString()->write()->writeValue(),
- * Fraction is recognized as a Number, and converted via
- * numberToString() into the unquoted string '4/2'. But the
- * BigDecimal sanity check fails, so writeValue() defaults
- * to returning a safe JSON quoted string. Pretty slick!
- */
- JSONObject jsonObject5 = new JSONObject();
- jsonObject5.put("myNumber", new Fraction(4,2));
- actual = jsonObject5.toString();
- expected = "{\"myNumber\":\"4/2\"}"; // valid JSON, bug fixed
- assertEquals("Equal", expected , actual);
-
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject0, jsonObject1, jsonObject2, jsonObject3, jsonObject4, jsonObject5
- )));
- }
-
- /**
- * Verifies that the put Collection has backwards compatibility with RAW types pre-java5.
- */
- @Test
- public void verifyPutCollection() {
-
- final JSONObject expected = new JSONObject("{\"myCollection\":[10]}");
-
- @SuppressWarnings("rawtypes")
- Collection myRawC = Collections.singleton(Integer.valueOf(10));
- JSONObject jaRaw = new JSONObject();
- jaRaw.put("myCollection", myRawC);
-
- Collection myCObj = Collections.singleton((Object) Integer
- .valueOf(10));
- JSONObject jaObj = new JSONObject();
- jaObj.put("myCollection", myCObj);
-
- Collection myCInt = Collections.singleton(Integer
- .valueOf(10));
- JSONObject jaInt = new JSONObject();
- jaInt.put("myCollection", myCInt);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObj));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaInt));
-
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jaRaw, jaObj, jaInt
- )));
- }
-
-
- /**
- * Verifies that the put Map has backwards compatibility with RAW types pre-java5.
- */
- @Test
- public void verifyPutMap() {
-
- final JSONObject expected = new JSONObject("{\"myMap\":{\"myKey\":10}}");
-
- @SuppressWarnings("rawtypes")
- Map myRawC = Collections.singletonMap("myKey", Integer.valueOf(10));
- JSONObject jaRaw = new JSONObject();
- jaRaw.put("myMap", myRawC);
-
- Map myCStrObj = Collections.singletonMap("myKey",
- (Object) Integer.valueOf(10));
- JSONObject jaStrObj = new JSONObject();
- jaStrObj.put("myMap", myCStrObj);
-
- Map myCStrInt = Collections.singletonMap("myKey",
- Integer.valueOf(10));
- JSONObject jaStrInt = new JSONObject();
- jaStrInt.put("myMap", myCStrInt);
-
- Map, ?> myCObjObj = Collections.singletonMap((Object) "myKey",
- (Object) Integer.valueOf(10));
- JSONObject jaObjObj = new JSONObject();
- jaObjObj.put("myMap", myCObjObj);
-
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaRaw));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrObj));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaStrInt));
- assertTrue(
- "The RAW Collection should give me the same as the Typed Collection",
- expected.similar(jaObjObj));
-
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jaRaw, jaStrObj, jaStrInt, jaStrObj
- )));
- }
-
-
- /**
- * JSONObjects can be built from a Map.
- * In this test the map entries are not valid JSON types.
- * The actual conversion is kind of interesting.
- */
- @Test
- public void jsonObjectByMapWithUnsupportedValues() {
- Map jsonMap = new HashMap();
- // Just insert some random objects
- jsonMap.put("key1", new CDL());
- jsonMap.put("key2", new Exception());
-
- JSONObject jsonObject = new JSONObject(jsonMap);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected 0 key1 items", ((Map,?>)(JsonPath.read(doc, "$.key1"))).size() == 0);
- assertTrue("expected \"key2\":java.lang.Exception","java.lang.Exception".equals(jsonObject.query("/key2")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * JSONObjects can be built from a Map.
- * In this test one of the map values is null
- */
- @Test
- public void jsonObjectByMapWithNullValue() {
- Map map = new HashMap();
- map.put("trueKey", Boolean.valueOf(true));
- map.put("falseKey", Boolean.valueOf(false));
- map.put("stringKey", "hello world!");
- map.put("nullKey", null);
- map.put("escapeStringKey", "h\be\tllo w\u1234orld!");
- map.put("intKey", Long.valueOf(42));
- map.put("doubleKey", Double.valueOf(-23.45e67));
- JSONObject jsonObject = new JSONObject(map);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected \"trueKey\":true", Boolean.TRUE.equals(jsonObject.query("/trueKey")));
- assertTrue("expected \"falseKey\":false", Boolean.FALSE.equals(jsonObject.query("/falseKey")));
- assertTrue("expected \"stringKey\":\"hello world!\"", "hello world!".equals(jsonObject.query("/stringKey")));
- assertTrue("expected \"escapeStringKey\":\"h\be\tllo w\u1234orld!\"", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/escapeStringKey")));
- assertTrue("expected \"intKey\":42", Long.valueOf("42").equals(jsonObject.query("/intKey")));
- assertTrue("expected \"doubleKey\":-23.45e67", Double.valueOf("-23.45e67").equals(jsonObject.query("/doubleKey")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- @Test
- public void jsonObjectByMapWithNullValueAndParserConfiguration() {
- Map map = new HashMap();
- map.put("nullKey", null);
-
- // by default, null values are ignored
- JSONObject obj1 = new JSONObject(map);
- assertTrue("expected null value to be ignored by default", obj1.isEmpty());
-
- // if configured, null values are written as such into the JSONObject.
- JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withUseNativeNulls(true);
- JSONObject obj2 = new JSONObject(map, parserConfiguration);
- assertFalse("expected null value to accepted when configured", obj2.isEmpty());
- assertTrue(obj2.has("nullKey"));
- assertEquals(JSONObject.NULL, obj2.get("nullKey"));
- }
-
- @Test
- public void jsonObjectByMapWithNestedNullValueAndParserConfiguration() {
- Map map = new HashMap();
- Map nestedMap = new HashMap();
- nestedMap.put("nullKey", null);
- map.put("nestedMap", nestedMap);
- List> nestedList = new ArrayList>();
- nestedList.add(nestedMap);
- map.put("nestedList", nestedList);
-
- JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withUseNativeNulls(true);
- JSONObject jsonObject = new JSONObject(map, parserConfiguration);
-
- JSONObject nestedObject = jsonObject.getJSONObject("nestedMap");
- assertTrue(nestedObject.has("nullKey"));
- assertEquals(JSONObject.NULL, nestedObject.get("nullKey"));
-
- JSONArray nestedArray = jsonObject.getJSONArray("nestedList");
- assertEquals(1, nestedArray.length());
- assertTrue(nestedArray.getJSONObject(0).has("nullKey"));
- assertEquals(JSONObject.NULL, nestedArray.getJSONObject(0).get("nullKey"));
- }
-
- /**
- * JSONObject built from a bean. In this case all but one of the
- * bean getters return valid JSON types
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectByBean1() {
- /**
- * Default access classes have to be mocked since JSONObject, which is
- * not in the same package, cannot call MyBean methods by reflection.
- */
- MyBean myBean = mock(MyBean.class);
- when(myBean.getDoubleKey()).thenReturn(-23.45e7);
- when(myBean.getIntKey()).thenReturn(42);
- when(myBean.getStringKey()).thenReturn("hello world!");
- when(myBean.getEscapeStringKey()).thenReturn("h\be\tllo w\u1234orld!");
- when(myBean.isTrueKey()).thenReturn(true);
- when(myBean.isFalseKey()).thenReturn(false);
- when(myBean.getStringReaderKey()).thenReturn(
- new StringReader("") {
- });
-
- JSONObject jsonObject = new JSONObject(myBean);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 8 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 8);
- assertTrue("expected 0 items in stringReaderKey", ((Map, ?>) (JsonPath.read(doc, "$.stringReaderKey"))).size() == 0);
- assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueKey")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseKey")));
- assertTrue("expected hello world!","hello world!".equals(jsonObject.query("/stringKey")));
- assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/escapeStringKey")));
- assertTrue("expected 42", Integer.valueOf("42").equals(jsonObject.query("/intKey")));
- assertTrue("expected -23.45e7", Double.valueOf("-23.45e7").equals(jsonObject.query("/doubleKey")));
- // sorry, mockito artifact
- assertTrue("expected 2 mockitoInterceptor items", ((Map,?>)(JsonPath.read(doc, "$.mockitoInterceptor"))).size() == 2);
- assertTrue("expected 0 mockitoInterceptor.serializationSupport items",
- ((Map,?>)(JsonPath.read(doc, "$.mockitoInterceptor.serializationSupport"))).size() == 0);
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * JSONObject built from a bean that has custom field names.
- */
- @Test
- public void jsonObjectByBean2() {
- JSONObject jsonObject = new JSONObject(new MyBeanCustomName());
- assertNotNull(jsonObject);
- assertEquals("Wrong number of keys found:",
- 5,
- jsonObject.keySet().size());
- assertFalse("Normal field name (someString) processing did not work",
- jsonObject.has("someString"));
- assertFalse("Normal field name (myDouble) processing did not work",
- jsonObject.has("myDouble"));
- assertFalse("Normal field name (someFloat) processing did not work",
- jsonObject.has("someFloat"));
- assertFalse("Ignored field not found!",
- jsonObject.has("ignoredInt"));
- // getSomeInt() has no user-defined annotation
- assertTrue("Normal field name (someInt) should have been found",
- jsonObject.has("someInt"));
- // the user-defined annotation does not replace any value, so someLong should be found
- assertTrue("Normal field name (someLong) should have been found",
- jsonObject.has("someLong"));
- // myStringField replaces someString property name via user-defined annotation
- assertTrue("Overridden String field name (myStringField) should have been found",
- jsonObject.has("myStringField"));
- // weird name replaces myDouble property name via user-defined annotation
- assertTrue("Overridden String field name (Some Weird NAme that Normally Wouldn't be possible!) should have been found",
- jsonObject.has("Some Weird NAme that Normally Wouldn't be possible!"));
- // InterfaceField replaces someFloat property name via user-defined annotation
- assertTrue("Overridden String field name (InterfaceField) should have been found",
- jsonObject.has("InterfaceField"));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * JSONObject built from a bean that has custom field names inherited from a parent class.
- */
- @Test
- public void jsonObjectByBean3() {
- JSONObject jsonObject = new JSONObject(new MyBeanCustomNameSubClass());
- assertNotNull(jsonObject);
- assertEquals("Wrong number of keys found:",
- 7,
- jsonObject.keySet().size());
- assertFalse("Normal int field name (someInt) found, but was overridden",
- jsonObject.has("someInt"));
- assertFalse("Normal field name (myDouble) processing did not work",
- jsonObject.has("myDouble"));
- // myDouble was replaced by weird name, and then replaced again by AMoreNormalName via user-defined annotation
- assertFalse("Overridden String field name (Some Weird NAme that Normally Wouldn't be possible!) should not be FOUND!",
- jsonObject.has("Some Weird NAme that Normally Wouldn't be possible!"));
- assertFalse("Normal field name (someFloat) found, but was overridden",
- jsonObject.has("someFloat"));
- assertFalse("Ignored field found! but was overridden",
- jsonObject.has("ignoredInt"));
- // shouldNotBeJSON property name was first ignored, then replaced by ShouldBeIgnored via user-defined annotations
- assertFalse("Ignored field at the same level as forced name should not have been found",
- jsonObject.has("ShouldBeIgnored"));
- // able property name was replaced by Getable via user-defined annotation
- assertFalse("Normally ignored field (able) with explicit property name should not have been found",
- jsonObject.has("able"));
- // property name someInt was replaced by newIntFieldName via user-defined annotation
- assertTrue("Overridden int field name (newIntFieldName) should have been found",
- jsonObject.has("newIntFieldName"));
- // property name someLong was not replaced via user-defined annotation
- assertTrue("Normal field name (someLong) should have been found",
- jsonObject.has("someLong"));
- // property name someString was replaced by myStringField via user-defined annotation
- assertTrue("Overridden String field name (myStringField) should have been found",
- jsonObject.has("myStringField"));
- // property name myDouble was replaced by a weird name, followed by AMoreNormalName via user-defined annotations
- assertTrue("Overridden double field name (AMoreNormalName) should have been found",
- jsonObject.has("AMoreNormalName"));
- // property name someFloat was replaced by InterfaceField via user-defined annotation
- assertTrue("Overridden String field name (InterfaceField) should have been found",
- jsonObject.has("InterfaceField"));
- // property name ignoredInt was replaced by none, followed by forcedInt via user-defined annotations
- assertTrue("Forced field should have been found!",
- jsonObject.has("forcedInt"));
- // property name able was replaced by Getable via user-defined annotation
- assertTrue("Overridden boolean field name (Getable) should have been found",
- jsonObject.has("Getable"));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * A bean is also an object. But in order to test the JSONObject
- * ctor that takes an object and a list of names,
- * this particular bean needs some public
- * data members, which have been added to the class.
- */
- @Test
- public void jsonObjectByObjectAndNames() {
- String[] keys = {"publicString", "publicInt"};
- // just need a class that has public data members
- MyPublicClass myPublicClass = new MyPublicClass();
- JSONObject jsonObject = new JSONObject(myPublicClass, keys);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected \"publicString\":\"abc\"", "abc".equals(jsonObject.query("/publicString")));
- assertTrue("expected \"publicInt\":42", Integer.valueOf(42).equals(jsonObject.query("/publicInt")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONObject from resource bundle functionality.
- * The test resource bundle is uncomplicated, but provides adequate test coverage.
- */
- @Test
- public void jsonObjectByResourceBundle() {
- JSONObject jsonObject = new
- JSONObject("org.json.junit.data.StringsResourceBundle",
- Locale.getDefault());
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 2 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 2);
- assertTrue("expected 2 greetings items", ((Map,?>)(JsonPath.read(doc, "$.greetings"))).size() == 2);
- assertTrue("expected \"hello\":\"Hello, \"", "Hello, ".equals(jsonObject.query("/greetings/hello")));
- assertTrue("expected \"world\":\"World!\"", "World!".equals(jsonObject.query("/greetings/world")));
- assertTrue("expected 2 farewells items", ((Map,?>)(JsonPath.read(doc, "$.farewells"))).size() == 2);
- assertTrue("expected \"later\":\"Later, \"", "Later, ".equals(jsonObject.query("/farewells/later")));
- assertTrue("expected \"world\":\"World!\"", "Alligator!".equals(jsonObject.query("/farewells/gator")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONObject.accumulate() method
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectAccumulate() {
-
- JSONObject jsonObject = new JSONObject();
- jsonObject.accumulate("myArray", true);
- jsonObject.accumulate("myArray", false);
- jsonObject.accumulate("myArray", "hello world!");
- jsonObject.accumulate("myArray", "h\be\tllo w\u1234orld!");
- jsonObject.accumulate("myArray", 42);
- jsonObject.accumulate("myArray", -23.45e7);
- // include an unsupported object for coverage
- try {
- jsonObject.accumulate("myArray", Double.NaN);
- fail("Expected exception");
- } catch (JSONException ignored) {}
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 6 myArray items", ((List>)(JsonPath.read(doc, "$.myArray"))).size() == 6);
- assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/myArray/0")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/myArray/1")));
- assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/myArray/2")));
- assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/myArray/3")));
- assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/myArray/4")));
- assertTrue("expected -23.45e7", Double.valueOf(-23.45e7).equals(jsonObject.query("/myArray/5")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONObject append() functionality
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectAppend() {
- JSONObject jsonObject = new JSONObject();
- jsonObject.append("myArray", true);
- jsonObject.append("myArray", false);
- jsonObject.append("myArray", "hello world!");
- jsonObject.append("myArray", "h\be\tllo w\u1234orld!");
- jsonObject.append("myArray", 42);
- jsonObject.append("myArray", -23.45e7);
- // include an unsupported object for coverage
- try {
- jsonObject.append("myArray", Double.NaN);
- fail("Expected exception");
- } catch (JSONException ignored) {}
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 6 myArray items", ((List>)(JsonPath.read(doc, "$.myArray"))).size() == 6);
- assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/myArray/0")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/myArray/1")));
- assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/myArray/2")));
- assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/myArray/3")));
- assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/myArray/4")));
- assertTrue("expected -23.45e7", Double.valueOf(-23.45e7).equals(jsonObject.query("/myArray/5")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONObject doubleToString() method
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectDoubleToString() {
- String [] expectedStrs = {"1", "1", "-23.4", "-2.345E68", "null", "null" };
- Double [] doubles = { 1.0, 00001.00000, -23.4, -23.45e67,
- Double.NaN, Double.NEGATIVE_INFINITY };
- for (int i = 0; i < expectedStrs.length; ++i) {
- String actualStr = JSONObject.doubleToString(doubles[i]);
- assertTrue("value expected ["+expectedStrs[i]+
- "] found ["+actualStr+ "]",
- expectedStrs[i].equals(actualStr));
- }
- }
-
- /**
- * Exercise some JSONObject get[type] and opt[type] methods
- */
- @Test
- public void jsonObjectValues() {
- String str =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"trueStrKey\":\"true\","+
- "\"falseStrKey\":\"false\","+
- "\"stringKey\":\"hello world!\","+
- "\"intKey\":42,"+
- "\"intStrKey\":\"43\","+
- "\"longKey\":1234567890123456789,"+
- "\"longStrKey\":\"987654321098765432\","+
- "\"doubleKey\":-23.45e7,"+
- "\"doubleStrKey\":\"00001.000\","+
- "\"BigDecimalStrKey\":\"19007199254740993.35481234487103587486413587843213584\","+
- "\"negZeroKey\":-0.0,"+
- "\"negZeroStrKey\":\"-0.0\","+
- "\"arrayKey\":[0,1,2],"+
- "\"objectKey\":{\"myKey\":\"myVal\"}"+
- "}";
- JSONObject jsonObject = new JSONObject(str);
- assertTrue("trueKey should be true", jsonObject.getBoolean("trueKey"));
- assertTrue("opt trueKey should be true", jsonObject.optBoolean("trueKey"));
- assertTrue("opt trueKey should be true", jsonObject.optBooleanObject("trueKey"));
- assertTrue("falseKey should be false", !jsonObject.getBoolean("falseKey"));
- assertTrue("trueStrKey should be true", jsonObject.getBoolean("trueStrKey"));
- assertTrue("trueStrKey should be true", jsonObject.optBoolean("trueStrKey"));
- assertTrue("trueStrKey should be true", jsonObject.optBooleanObject("trueStrKey"));
- assertTrue("falseStrKey should be false", !jsonObject.getBoolean("falseStrKey"));
- assertTrue("stringKey should be string",
- jsonObject.getString("stringKey").equals("hello world!"));
- assertTrue("doubleKey should be double",
- jsonObject.getDouble("doubleKey") == -23.45e7);
- assertTrue("doubleStrKey should be double",
- jsonObject.getDouble("doubleStrKey") == 1);
- assertTrue("doubleKey can be float",
- jsonObject.getFloat("doubleKey") == -23.45e7f);
- assertTrue("doubleStrKey can be float",
- jsonObject.getFloat("doubleStrKey") == 1f);
- assertTrue("opt doubleKey should be double",
- jsonObject.optDouble("doubleKey") == -23.45e7);
- assertTrue("opt doubleKey with Default should be double",
- jsonObject.optDouble("doubleStrKey", Double.NaN) == 1);
- assertTrue("opt doubleKey should be Double",
- Double.valueOf(-23.45e7).equals(jsonObject.optDoubleObject("doubleKey")));
- assertTrue("opt doubleKey with Default should be Double",
- Double.valueOf(1).equals(jsonObject.optDoubleObject("doubleStrKey", Double.NaN)));
- assertTrue("opt negZeroKey should be a Double",
- jsonObject.opt("negZeroKey") instanceof Double);
- assertTrue("get negZeroKey should be a Double",
- jsonObject.get("negZeroKey") instanceof Double);
- assertTrue("optNumber negZeroKey should return Double",
- jsonObject.optNumber("negZeroKey") instanceof Double);
- assertTrue("optNumber negZeroStrKey should return Double",
- jsonObject.optNumber("negZeroStrKey") instanceof Double);
- assertTrue("opt negZeroKey should be double",
- Double.compare(jsonObject.optDouble("negZeroKey"), -0.0d) == 0);
- assertTrue("opt negZeroStrKey with Default should be double",
- Double.compare(jsonObject.optDouble("negZeroStrKey"), -0.0d) == 0);
- assertTrue("opt negZeroKey should be Double",
- Double.valueOf(-0.0d).equals(jsonObject.optDoubleObject("negZeroKey")));
- assertTrue("opt negZeroStrKey with Default should be Double",
- Double.valueOf(-0.0d).equals(jsonObject.optDoubleObject("negZeroStrKey")));
- assertTrue("optNumber negZeroKey should be -0.0",
- Double.compare(jsonObject.optNumber("negZeroKey").doubleValue(), -0.0d) == 0);
- assertTrue("optNumber negZeroStrKey should be -0.0",
- Double.compare(jsonObject.optNumber("negZeroStrKey").doubleValue(), -0.0d) == 0);
- assertTrue("optFloat doubleKey should be float",
- jsonObject.optFloat("doubleKey") == -23.45e7f);
- assertTrue("optFloat doubleKey with Default should be float",
- jsonObject.optFloat("doubleStrKey", Float.NaN) == 1f);
- assertTrue("optFloat doubleKey should be Float",
- Float.valueOf(-23.45e7f).equals(jsonObject.optFloatObject("doubleKey")));
- assertTrue("optFloat doubleKey with Default should be Float",
- Float.valueOf(1f).equals(jsonObject.optFloatObject("doubleStrKey", Float.NaN)));
- assertTrue("intKey should be int",
- jsonObject.optInt("intKey") == 42);
- assertTrue("opt intKey should be int",
- jsonObject.optInt("intKey", 0) == 42);
- assertTrue("intKey should be Integer",
- Integer.valueOf(42).equals(jsonObject.optIntegerObject("intKey")));
- assertTrue("opt intKey should be Integer",
- Integer.valueOf(42).equals(jsonObject.optIntegerObject("intKey", 0)));
- assertTrue("opt intKey with default should be int",
- jsonObject.getInt("intKey") == 42);
- assertTrue("intStrKey should be int",
- jsonObject.getInt("intStrKey") == 43);
- assertTrue("longKey should be long",
- jsonObject.getLong("longKey") == 1234567890123456789L);
- assertTrue("opt longKey should be long",
- jsonObject.optLong("longKey") == 1234567890123456789L);
- assertTrue("opt longKey with default should be long",
- jsonObject.optLong("longKey", 0) == 1234567890123456789L);
- assertTrue("opt longKey should be Long",
- Long.valueOf(1234567890123456789L).equals(jsonObject.optLongObject("longKey")));
- assertTrue("opt longKey with default should be Long",
- Long.valueOf(1234567890123456789L).equals(jsonObject.optLongObject("longKey", 0L)));
- assertTrue("longStrKey should be long",
- jsonObject.getLong("longStrKey") == 987654321098765432L);
- assertTrue("optNumber int should return Integer",
- jsonObject.optNumber("intKey") instanceof Integer);
- assertTrue("optNumber long should return Long",
- jsonObject.optNumber("longKey") instanceof Long);
- assertTrue("optNumber double should return BigDecimal",
- jsonObject.optNumber("doubleKey") instanceof BigDecimal);
- assertTrue("optNumber Str int should return Integer",
- jsonObject.optNumber("intStrKey") instanceof Integer);
- assertTrue("optNumber Str long should return Long",
- jsonObject.optNumber("longStrKey") instanceof Long);
- assertTrue("optNumber Str double should return BigDecimal",
- jsonObject.optNumber("doubleStrKey") instanceof BigDecimal);
- assertTrue("optNumber BigDecimalStrKey should return BigDecimal",
- jsonObject.optNumber("BigDecimalStrKey") instanceof BigDecimal);
- assertTrue("xKey should not exist",
- jsonObject.isNull("xKey"));
- assertTrue("stringKey should exist",
- jsonObject.has("stringKey"));
- assertTrue("opt stringKey should string",
- jsonObject.optString("stringKey").equals("hello world!"));
- assertTrue("opt stringKey with default should string",
- jsonObject.optString("stringKey", "not found").equals("hello world!"));
- JSONArray jsonArray = jsonObject.getJSONArray("arrayKey");
- assertTrue("arrayKey should be JSONArray",
- jsonArray.getInt(0) == 0 &&
- jsonArray.getInt(1) == 1 &&
- jsonArray.getInt(2) == 2);
- jsonArray = jsonObject.optJSONArray("arrayKey");
- assertTrue("opt arrayKey should be JSONArray",
- jsonArray.getInt(0) == 0 &&
- jsonArray.getInt(1) == 1 &&
- jsonArray.getInt(2) == 2);
- JSONObject jsonObjectInner = jsonObject.getJSONObject("objectKey");
- assertTrue("objectKey should be JSONObject",
- jsonObjectInner.get("myKey").equals("myVal"));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Check whether JSONObject handles large or high precision numbers correctly
- */
- @Test
- public void stringToValueNumbersTest() {
- assertTrue("-0 Should be a Double!",JSONObject.stringToValue("-0") instanceof Double);
- assertTrue("-0.0 Should be a Double!",JSONObject.stringToValue("-0.0") instanceof Double);
- assertTrue("'-' Should be a String!",JSONObject.stringToValue("-") instanceof String);
- assertTrue( "0.2 should be a BigDecimal!",
- JSONObject.stringToValue( "0.2" ) instanceof BigDecimal );
- assertTrue( "Doubles should be BigDecimal, even when incorrectly converting floats!",
- JSONObject.stringToValue( Double.valueOf( "0.2f" ).toString() ) instanceof BigDecimal );
- /**
- * This test documents a need for BigDecimal conversion.
- */
- Object obj = JSONObject.stringToValue( "299792.457999999984" );
- assertTrue( "does not evaluate to 299792.457999999984 BigDecimal!",
- obj.equals(new BigDecimal("299792.457999999984")) );
- assertTrue( "1 should be an Integer!",
- JSONObject.stringToValue( "1" ) instanceof Integer );
- assertTrue( "Integer.MAX_VALUE should still be an Integer!",
- JSONObject.stringToValue( Integer.valueOf( Integer.MAX_VALUE ).toString() ) instanceof Integer );
- assertTrue( "Large integers should be a Long!",
- JSONObject.stringToValue( Long.valueOf(((long)Integer.MAX_VALUE) + 1 ) .toString() ) instanceof Long );
- assertTrue( "Long.MAX_VALUE should still be an Integer!",
- JSONObject.stringToValue( Long.valueOf( Long.MAX_VALUE ).toString() ) instanceof Long );
-
- String str = new BigInteger( Long.valueOf( Long.MAX_VALUE ).toString() ).add( BigInteger.ONE ).toString();
- assertTrue( "Really large integers currently evaluate to BigInteger",
- JSONObject.stringToValue(str).equals(new BigInteger("9223372036854775808")));
- }
-
- /**
- * This test documents numeric values which could be numerically
- * handled as BigDecimal or BigInteger. It helps determine what outputs
- * will change if those types are supported.
- */
- @Test
- public void jsonValidNumberValuesNeitherLongNorIEEE754Compatible() {
- // Valid JSON Numbers, probably should return BigDecimal or BigInteger objects
- String str =
- "{"+
- "\"numberWithDecimals\":299792.457999999984,"+
- "\"largeNumber\":12345678901234567890,"+
- "\"preciseNumber\":0.2000000000000000111,"+
- "\"largeExponent\":-23.45e2327"+
- "}";
- JSONObject jsonObject = new JSONObject(str);
- // Comes back as a double, but loses precision
- assertTrue( "numberWithDecimals currently evaluates to double 299792.458",
- jsonObject.get( "numberWithDecimals" ).equals( new BigDecimal( "299792.457999999984" ) ) );
- Object obj = jsonObject.get( "largeNumber" );
- assertTrue("largeNumber currently evaluates to BigInteger",
- new BigInteger("12345678901234567890").equals(obj));
- // comes back as a double but loses precision
- assertEquals( "preciseNumber currently evaluates to double 0.2",
- 0.2, jsonObject.getDouble( "preciseNumber" ), 0.0);
- obj = jsonObject.get( "largeExponent" );
- assertTrue("largeExponent should evaluate as a BigDecimal",
- new BigDecimal("-23.45e2327").equals(obj));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * This test documents how JSON-Java handles invalid numeric input.
- */
- @Test
- public void jsonInvalidNumberValues() {
- // Number-notations supported by Java and invalid as JSON
- String str =
- "{" +
- "\"hexNumber\":-0x123," +
- "\"tooManyZeros\":00," +
- "\"negativeInfinite\":-Infinity," +
- "\"negativeNaN\":-NaN," +
- "\"negativeFraction\":-.01," +
- "\"tooManyZerosFraction\":00.001," +
- "\"negativeHexFloat\":-0x1.fffp1," +
- "\"hexFloat\":0x1.0P-1074," +
- "\"floatIdentifier\":0.1f," +
- "\"doubleIdentifier\":0.1d" +
- "}";
-
- // Test should fail if default strictMode is true, pass if false
- JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
- if (jsonParserConfiguration.isStrictMode()) {
- try {
- JSONObject jsonObject = new JSONObject(str);
- assertEquals("Expected to throw exception due to invalid string", true, false);
- } catch (JSONException e) { }
- } else {
- JSONObject jsonObject = new JSONObject(str);
- Object obj;
- obj = jsonObject.get("hexNumber");
- assertFalse("hexNumber must not be a number (should throw exception!?)",
- obj instanceof Number);
- assertTrue("hexNumber currently evaluates to string",
- obj.equals("-0x123"));
- assertTrue("tooManyZeros currently evaluates to string",
- jsonObject.get("tooManyZeros").equals("00"));
- obj = jsonObject.get("negativeInfinite");
- assertTrue("negativeInfinite currently evaluates to string",
- obj.equals("-Infinity"));
- obj = jsonObject.get("negativeNaN");
- assertTrue("negativeNaN currently evaluates to string",
- obj.equals("-NaN"));
- assertTrue("negativeFraction currently evaluates to double -0.01",
- jsonObject.get("negativeFraction").equals(BigDecimal.valueOf(-0.01)));
- assertTrue("tooManyZerosFraction currently evaluates to double 0.001",
- jsonObject.optLong("tooManyZerosFraction") == 0);
- assertTrue("negativeHexFloat currently evaluates to double -3.99951171875",
- jsonObject.get("negativeHexFloat").equals(Double.valueOf(-3.99951171875)));
- assertTrue("hexFloat currently evaluates to double 4.9E-324",
- jsonObject.get("hexFloat").equals(Double.valueOf(4.9E-324)));
- assertTrue("floatIdentifier currently evaluates to double 0.1",
- jsonObject.get("floatIdentifier").equals(Double.valueOf(0.1)));
- assertTrue("doubleIdentifier currently evaluates to double 0.1",
- jsonObject.get("doubleIdentifier").equals(Double.valueOf(0.1)));
- Util.checkJSONObjectMaps(jsonObject);
- }
- }
-
- /**
- * Tests how JSONObject get[type] handles incorrect types
- */
- @Test
- public void jsonObjectNonAndWrongValues() {
- String str =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"trueStrKey\":\"true\","+
- "\"falseStrKey\":\"false\","+
- "\"stringKey\":\"hello world!\","+
- "\"intKey\":42,"+
- "\"intStrKey\":\"43\","+
- "\"longKey\":1234567890123456789,"+
- "\"longStrKey\":\"987654321098765432\","+
- "\"doubleKey\":-23.45e7,"+
- "\"doubleStrKey\":\"00001.000\","+
- "\"arrayKey\":[0,1,2],"+
- "\"objectKey\":{\"myKey\":\"myVal\"}"+
- "}";
- JSONObject jsonObject = new JSONObject(str);
- try {
- jsonObject.getBoolean("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("expecting an exception message",
- "JSONObject[\"nonKey\"] not found.", e.getMessage());
- }
- try {
- jsonObject.getBoolean("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a Boolean (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getString("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getString("trueKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"trueKey\"] is not a string (class java.lang.Boolean : true).",
- e.getMessage());
- }
- try {
- jsonObject.getDouble("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getDouble("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a double (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getFloat("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getFloat("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a float (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getInt("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getInt("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a int (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getLong("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getLong("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a long (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getJSONArray("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getJSONArray("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a JSONArray (class java.lang.String : hello world!).",
- e.getMessage());
- }
- try {
- jsonObject.getJSONObject("nonKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"nonKey\"] not found.",
- e.getMessage());
- }
- try {
- jsonObject.getJSONObject("stringKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"stringKey\"] is not a JSONObject (class java.lang.String : hello world!).",
- e.getMessage());
- }
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * This test documents an unexpected numeric behavior.
- * A double that ends with .0 is parsed, serialized, then
- * parsed again. On the second parse, it has become an int.
- */
- @Test
- public void unexpectedDoubleToIntConversion() {
- String key30 = "key30";
- String key31 = "key31";
- JSONObject jsonObject = new JSONObject();
- jsonObject.put(key30, Double.valueOf(3.0));
- jsonObject.put(key31, Double.valueOf(3.1));
-
- assertTrue("3.0 should remain a double",
- jsonObject.getDouble(key30) == 3);
- assertTrue("3.1 should remain a double",
- jsonObject.getDouble(key31) == 3.1);
-
- // turns 3.0 into 3.
- String serializedString = jsonObject.toString();
- JSONObject deserialized = new JSONObject(serializedString);
- assertTrue("3.0 is now an int", deserialized.get(key30) instanceof Integer);
- assertTrue("3.0 can still be interpreted as a double",
- deserialized.getDouble(key30) == 3.0);
- assertTrue("3.1 remains a double", deserialized.getDouble(key31) == 3.1);
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Document behaviors of big numbers. Includes both JSONObject
- * and JSONArray tests
- */
- @SuppressWarnings("boxing")
- @Test
- public void bigNumberOperations() {
- /**
- * JSONObject tries to parse BigInteger as a bean, but it only has
- * one getter, getLowestBitSet(). The value is lost and an unhelpful
- * value is stored. This should be fixed.
- */
- BigInteger bigInteger = new BigInteger("123456789012345678901234567890");
- JSONObject jsonObject0 = new JSONObject(bigInteger);
- Object obj = jsonObject0.get("lowestSetBit");
- assertTrue("JSONObject only has 1 value", jsonObject0.length() == 1);
- assertTrue("JSONObject parses BigInteger as the Integer lowestBitSet",
- obj instanceof Integer);
- assertTrue("this bigInteger lowestBitSet happens to be 1",
- obj.equals(1));
-
- /**
- * JSONObject tries to parse BigDecimal as a bean, but it has
- * no getters, The value is lost and no value is stored.
- * This should be fixed.
- */
- BigDecimal bigDecimal = new BigDecimal(
- "123456789012345678901234567890.12345678901234567890123456789");
- JSONObject jsonObject1 = new JSONObject(bigDecimal);
- assertTrue("large bigDecimal is not stored", jsonObject1.isEmpty());
-
- /**
- * JSONObject put(String, Object) method stores and serializes
- * bigInt and bigDec correctly. Nothing needs to change.
- */
- JSONObject jsonObject2 = new JSONObject();
- jsonObject2.put("bigInt", bigInteger);
- assertTrue("jsonObject.put() handles bigInt correctly",
- jsonObject2.get("bigInt").equals(bigInteger));
- assertTrue("jsonObject.getBigInteger() handles bigInt correctly",
- jsonObject2.getBigInteger("bigInt").equals(bigInteger));
- assertTrue("jsonObject.optBigInteger() handles bigInt correctly",
- jsonObject2.optBigInteger("bigInt", BigInteger.ONE).equals(bigInteger));
- assertTrue("jsonObject serializes bigInt correctly",
- jsonObject2.toString().equals("{\"bigInt\":123456789012345678901234567890}"));
- assertTrue("BigInteger as BigDecimal",
- jsonObject2.getBigDecimal("bigInt").equals(new BigDecimal(bigInteger)));
-
-
- JSONObject jsonObject3 = new JSONObject();
- jsonObject3.put("bigDec", bigDecimal);
- assertTrue("jsonObject.put() handles bigDec correctly",
- jsonObject3.get("bigDec").equals(bigDecimal));
- assertTrue("jsonObject.getBigDecimal() handles bigDec correctly",
- jsonObject3.getBigDecimal("bigDec").equals(bigDecimal));
- assertTrue("jsonObject.optBigDecimal() handles bigDec correctly",
- jsonObject3.optBigDecimal("bigDec", BigDecimal.ONE).equals(bigDecimal));
- assertTrue("jsonObject serializes bigDec correctly",
- jsonObject3.toString().equals(
- "{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
-
- assertTrue("BigDecimal as BigInteger",
- jsonObject3.getBigInteger("bigDec").equals(bigDecimal.toBigInteger()));
- /**
- * exercise some exceptions
- */
- try {
- // bigInt key does not exist
- jsonObject3.getBigDecimal("bigInt");
- fail("expected an exeption");
- } catch (JSONException ignored) {}
- obj = jsonObject3.optBigDecimal("bigInt", BigDecimal.ONE);
- assertTrue("expected BigDecimal", obj.equals(BigDecimal.ONE));
- jsonObject3.put("stringKey", "abc");
- try {
- jsonObject3.getBigDecimal("stringKey");
- fail("expected an exeption");
- } catch (JSONException ignored) {}
- obj = jsonObject3.optBigInteger("bigDec", BigInteger.ONE);
- assertTrue("expected BigInteger", obj instanceof BigInteger);
- assertEquals(bigDecimal.toBigInteger(), obj);
-
- /**
- * JSONObject.numberToString() works correctly, nothing to change.
- */
- String str = JSONObject.numberToString(bigInteger);
- assertTrue("numberToString() handles bigInteger correctly",
- str.equals("123456789012345678901234567890"));
- str = JSONObject.numberToString(bigDecimal);
- assertTrue("numberToString() handles bigDecimal correctly",
- str.equals("123456789012345678901234567890.12345678901234567890123456789"));
-
- /**
- * JSONObject.stringToValue() turns bigInt into an accurate string,
- * and rounds bigDec. This incorrect, but users may have come to
- * expect this behavior. Change would be marginally better, but
- * might inconvenience users.
- */
- obj = JSONObject.stringToValue(bigInteger.toString());
- assertTrue("stringToValue() turns bigInteger string into Number",
- obj instanceof Number);
- obj = JSONObject.stringToValue(bigDecimal.toString());
- assertTrue("stringToValue() changes bigDecimal Number",
- obj instanceof Number);
-
- /**
- * wrap() vs put() big number behavior is now the same.
- */
- // bigInt map ctor
- Map map = new HashMap();
- map.put("bigInt", bigInteger);
- JSONObject jsonObject4 = new JSONObject(map);
- String actualFromMapStr = jsonObject4.toString();
- assertTrue("bigInt in map (or array or bean) is a string",
- actualFromMapStr.equals(
- "{\"bigInt\":123456789012345678901234567890}"));
- // bigInt put
- JSONObject jsonObject5 = new JSONObject();
- jsonObject5.put("bigInt", bigInteger);
- String actualFromPutStr = jsonObject5.toString();
- assertTrue("bigInt from put is a number",
- actualFromPutStr.equals(
- "{\"bigInt\":123456789012345678901234567890}"));
- // bigDec map ctor
- map = new HashMap();
- map.put("bigDec", bigDecimal);
- JSONObject jsonObject6 = new JSONObject(map);
- actualFromMapStr = jsonObject6.toString();
- assertTrue("bigDec in map (or array or bean) is a bigDec",
- actualFromMapStr.equals(
- "{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
- // bigDec put
- JSONObject jsonObject7 = new JSONObject();
- jsonObject7.put("bigDec", bigDecimal);
- actualFromPutStr = jsonObject7.toString();
- assertTrue("bigDec from put is a number",
- actualFromPutStr.equals(
- "{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
- // bigInt,bigDec put
- JSONArray jsonArray0 = new JSONArray();
- jsonArray0.put(bigInteger);
- jsonArray0.put(bigDecimal);
- actualFromPutStr = jsonArray0.toString();
- assertTrue("bigInt, bigDec from put is a number",
- actualFromPutStr.equals(
- "[123456789012345678901234567890,123456789012345678901234567890.12345678901234567890123456789]"));
- assertTrue("getBigInt is bigInt", jsonArray0.getBigInteger(0).equals(bigInteger));
- assertTrue("getBigDec is bigDec", jsonArray0.getBigDecimal(1).equals(bigDecimal));
- assertTrue("optBigInt is bigInt", jsonArray0.optBigInteger(0, BigInteger.ONE).equals(bigInteger));
- assertTrue("optBigDec is bigDec", jsonArray0.optBigDecimal(1, BigDecimal.ONE).equals(bigDecimal));
- jsonArray0.put(Boolean.TRUE);
- try {
- jsonArray0.getBigInteger(2);
- fail("should not be able to get big int");
- } catch (Exception ignored) {}
- try {
- jsonArray0.getBigDecimal(2);
- fail("should not be able to get big dec");
- } catch (Exception ignored) {}
- assertTrue("optBigInt is default", jsonArray0.optBigInteger(2, BigInteger.ONE).equals(BigInteger.ONE));
- assertTrue("optBigDec is default", jsonArray0.optBigDecimal(2, BigDecimal.ONE).equals(BigDecimal.ONE));
-
- // bigInt,bigDec list ctor
- List list = new ArrayList();
- list.add(bigInteger);
- list.add(bigDecimal);
- JSONArray jsonArray1 = new JSONArray(list);
- String actualFromListStr = jsonArray1.toString();
- assertTrue("bigInt, bigDec in list is a bigInt, bigDec",
- actualFromListStr.equals(
- "[123456789012345678901234567890,123456789012345678901234567890.12345678901234567890123456789]"));
- // bigInt bean ctor
- MyBigNumberBean myBigNumberBean = mock(MyBigNumberBean.class);
- when(myBigNumberBean.getBigInteger()).thenReturn(new BigInteger("123456789012345678901234567890"));
- JSONObject jsonObject8 = new JSONObject(myBigNumberBean);
- String actualFromBeanStr = jsonObject8.toString();
- // can't do a full string compare because mockery adds an extra key/value
- assertTrue("bigInt from bean ctor is a bigInt",
- actualFromBeanStr.contains("123456789012345678901234567890"));
- // bigDec bean ctor
- myBigNumberBean = mock(MyBigNumberBean.class);
- when(myBigNumberBean.getBigDecimal()).thenReturn(new BigDecimal("123456789012345678901234567890.12345678901234567890123456789"));
- jsonObject8 = new JSONObject(myBigNumberBean);
- actualFromBeanStr = jsonObject8.toString();
- // can't do a full string compare because mockery adds an extra key/value
- assertTrue("bigDec from bean ctor is a bigDec",
- actualFromBeanStr.contains("123456789012345678901234567890.12345678901234567890123456789"));
- // bigInt,bigDec wrap()
- obj = JSONObject.wrap(bigInteger);
- assertTrue("wrap() returns big num",obj.equals(bigInteger));
- obj = JSONObject.wrap(bigDecimal);
- assertTrue("wrap() returns string",obj.equals(bigDecimal));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject0, jsonObject1, jsonObject2, jsonObject3, jsonObject4,
- jsonObject5, jsonObject6, jsonObject7, jsonObject8
- )));
- Util.checkJSONArrayMaps(jsonArray0, jsonObject0.getMapType());
- Util.checkJSONArrayMaps(jsonArray1, jsonObject0.getMapType());
- }
-
- /**
- * The purpose for the static method getNames() methods are not clear.
- * This method is not called from within JSON-Java. Most likely
- * uses are to prep names arrays for:
- * JSONObject(JSONObject jo, String[] names)
- * JSONObject(Object object, String names[]),
- */
- @Test
- public void jsonObjectNames() {
-
- // getNames() from null JSONObject
- assertTrue("null names from null Object",
- null == JSONObject.getNames((Object)null));
-
- // getNames() from object with no fields
- assertTrue("null names from Object with no fields",
- null == JSONObject.getNames(new MyJsonString()));
-
- // getNames from new JSONOjbect
- JSONObject jsonObject0 = new JSONObject();
- String [] names = JSONObject.getNames(jsonObject0);
- assertTrue("names should be null", names == null);
-
-
- // getNames() from empty JSONObject
- String emptyStr = "{}";
- JSONObject jsonObject1 = new JSONObject(emptyStr);
- assertTrue("empty JSONObject should have null names",
- null == JSONObject.getNames(jsonObject1));
-
- // getNames() from JSONObject
- String str =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"stringKey\":\"hello world!\""+
- "}";
- JSONObject jsonObject2 = new JSONObject(str);
- names = JSONObject.getNames(jsonObject2);
- JSONArray jsonArray0 = new JSONArray(names);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider()
- .parse(jsonArray0.toString());
- List> docList = JsonPath.read(doc, "$");
- assertTrue("expected 3 items", docList.size() == 3);
- assertTrue(
- "expected to find trueKey",
- ((List>) JsonPath.read(doc, "$[?(@=='trueKey')]")).size() == 1);
- assertTrue(
- "expected to find falseKey",
- ((List>) JsonPath.read(doc, "$[?(@=='falseKey')]")).size() == 1);
- assertTrue(
- "expected to find stringKey",
- ((List>) JsonPath.read(doc, "$[?(@=='stringKey')]")).size() == 1);
-
- /**
- * getNames() from an enum with properties has an interesting result.
- * It returns the enum values, not the selected enum properties
- */
- MyEnumField myEnumField = MyEnumField.VAL1;
- names = JSONObject.getNames(myEnumField);
-
- // validate JSON
- JSONArray jsonArray1 = new JSONArray(names);
- doc = Configuration.defaultConfiguration().jsonProvider()
- .parse(jsonArray1.toString());
- docList = JsonPath.read(doc, "$");
- assertTrue("expected 3 items", docList.size() == 3);
- assertTrue(
- "expected to find VAL1",
- ((List>) JsonPath.read(doc, "$[?(@=='VAL1')]")).size() == 1);
- assertTrue(
- "expected to find VAL2",
- ((List>) JsonPath.read(doc, "$[?(@=='VAL2')]")).size() == 1);
- assertTrue(
- "expected to find VAL3",
- ((List>) JsonPath.read(doc, "$[?(@=='VAL3')]")).size() == 1);
-
- /**
- * A bean is also an object. But in order to test the static
- * method getNames(), this particular bean needs some public
- * data members.
- */
- MyPublicClass myPublicClass = new MyPublicClass();
- names = JSONObject.getNames(myPublicClass);
-
- // validate JSON
- JSONArray jsonArray2 = new JSONArray(names);
- doc = Configuration.defaultConfiguration().jsonProvider()
- .parse(jsonArray2.toString());
- docList = JsonPath.read(doc, "$");
- assertTrue("expected 2 items", docList.size() == 2);
- assertTrue(
- "expected to find publicString",
- ((List>) JsonPath.read(doc, "$[?(@=='publicString')]")).size() == 1);
- assertTrue(
- "expected to find publicInt",
- ((List>) JsonPath.read(doc, "$[?(@=='publicInt')]")).size() == 1);
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject0, jsonObject1, jsonObject2
- )));
- Util.checkJSONArrayMaps(jsonArray0, jsonObject0.getMapType());
- Util.checkJSONArrayMaps(jsonArray1, jsonObject0.getMapType());
- Util.checkJSONArrayMaps(jsonArray2, jsonObject0.getMapType());
- }
-
- /**
- * Populate a JSONArray from an empty JSONObject names() method.
- * It should be empty.
- */
- @Test
- public void emptyJsonObjectNamesToJsonAray() {
- JSONObject jsonObject = new JSONObject();
- JSONArray jsonArray = jsonObject.names();
- assertTrue("jsonArray should be null", jsonArray == null);
- Util.checkJSONObjectMaps(jsonObject);
- Util.checkJSONArrayMaps(jsonArray, jsonObject.getMapType());
- }
-
- /**
- * Populate a JSONArray from a JSONObject names() method.
- * Confirm that it contains the expected names.
- */
- @Test
- public void jsonObjectNamesToJsonAray() {
- String str =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"stringKey\":\"hello world!\""+
- "}";
-
- JSONObject jsonObject = new JSONObject(str);
- JSONArray jsonArray = jsonObject.names();
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 3 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected to find trueKey", ((List>) JsonPath.read(doc, "$[?(@=='trueKey')]")).size() == 1);
- assertTrue("expected to find falseKey", ((List>) JsonPath.read(doc, "$[?(@=='falseKey')]")).size() == 1);
- assertTrue("expected to find stringKey", ((List>) JsonPath.read(doc, "$[?(@=='stringKey')]")).size() == 1);
- Util.checkJSONObjectMaps(jsonObject);
- Util.checkJSONArrayMaps(jsonArray, jsonObject.getMapType());
- }
-
- /**
- * Exercise the JSONObject increment() method.
- */
- @SuppressWarnings("cast")
- @Test
- public void jsonObjectIncrement() {
- String str =
- "{"+
- "\"keyLong\":9999999991,"+
- "\"keyDouble\":1.1"+
- "}";
- JSONObject jsonObject = new JSONObject(str);
- jsonObject.increment("keyInt");
- jsonObject.increment("keyInt");
- jsonObject.increment("keyLong");
- jsonObject.increment("keyDouble");
- jsonObject.increment("keyInt");
- jsonObject.increment("keyLong");
- jsonObject.increment("keyDouble");
- /**
- * JSONObject constructor won't handle these types correctly, but
- * adding them via put works.
- */
- jsonObject.put("keyFloat", 1.1f);
- jsonObject.put("keyBigInt", new BigInteger("123456789123456789123456789123456780"));
- jsonObject.put("keyBigDec", new BigDecimal("123456789123456789123456789123456780.1"));
- jsonObject.increment("keyFloat");
- jsonObject.increment("keyFloat");
- jsonObject.increment("keyBigInt");
- jsonObject.increment("keyBigDec");
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 6 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 6);
- assertTrue("expected 3", Integer.valueOf(3).equals(jsonObject.query("/keyInt")));
- assertTrue("expected 9999999993", Long.valueOf(9999999993L).equals(jsonObject.query("/keyLong")));
- assertTrue("expected 3.1", BigDecimal.valueOf(3.1).equals(jsonObject.query("/keyDouble")));
- assertTrue("expected 123456789123456789123456789123456781", new BigInteger("123456789123456789123456789123456781").equals(jsonObject.query("/keyBigInt")));
- assertTrue("expected 123456789123456789123456789123456781.1", new BigDecimal("123456789123456789123456789123456781.1").equals(jsonObject.query("/keyBigDec")));
-
- /**
- * Should work the same way on any platform! @see https://docs.oracle
- * .com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3 This is the
- * effect of a float to double conversion and is inherent to the
- * shortcomings of the IEEE 754 format, when converting 32-bit into
- * double-precision 64-bit. Java type-casts float to double. A 32 bit
- * float is type-casted to 64 bit double by simply appending zero-bits
- * to the mantissa (and extended the signed exponent by 3 bits.) and
- * there is no way to obtain more information than it is stored in the
- * 32-bits float.
- *
- * Like 1/3 cannot be represented as base10 number because it is
- * periodically, 1/5 (for example) cannot be represented as base2 number
- * since it is periodically in base2 (take a look at
- * http://www.h-schmidt.net/FloatConverter/) The same happens to 3.1,
- * that decimal number (base10 representation) is periodic in base2
- * representation, therefore appending zero-bits is inaccurate. Only
- * repeating the periodically occurring bits (0110) would be a proper
- * conversion. However one cannot detect from a 32 bit IEE754
- * representation which bits would "repeat infinitely", since the
- * missing bits would not fit into the 32 bit float, i.e. the
- * information needed simply is not there!
- */
- assertEquals(Float.valueOf(3.1f), jsonObject.query("/keyFloat"));
-
- /**
- * float f = 3.1f; double df = (double) f; double d = 3.1d;
- * System.out.println
- * (Integer.toBinaryString(Float.floatToRawIntBits(f)));
- * System.out.println
- * (Long.toBinaryString(Double.doubleToRawLongBits(df)));
- * System.out.println
- * (Long.toBinaryString(Double.doubleToRawLongBits(d)));
- *
- * - Float:
- * seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
- * 1000000010001100110011001100110
- * - Double
- * seeeeeeeeeeemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
- * 10000000 10001100110011001100110
- * 100000000001000110011001100110011000000000000000000000000000000
- * 100000000001000110011001100110011001100110011001100110011001101
- */
-
- /**
- * Examples of well documented but probably unexpected behavior in
- * java / with 32-bit float to 64-bit float conversion.
- */
- assertFalse("Document unexpected behaviour with explicit type-casting float as double!", (double)0.2f == 0.2d );
- assertFalse("Document unexpected behaviour with implicit type-cast!", 0.2f == 0.2d );
- Double d1 = Double.valueOf( 1.1f );
- Double d2 = Double.valueOf( "1.1f" );
- assertFalse( "Document implicit type cast from float to double before calling Double(double d) constructor", d1.equals( d2 ) );
-
- assertTrue( "Correctly converting float to double via base10 (string) representation!", Double.valueOf( 3.1d ).equals( Double.valueOf( Float.valueOf( 3.1f ).toString() ) ) );
-
- // Pinpointing the not so obvious "buggy" conversion from float to double in JSONObject
- JSONObject jo = new JSONObject();
- jo.put( "bug", 3.1f ); // will call put( String key, double value ) with implicit and "buggy" type-cast from float to double
- assertFalse( "The java-compiler did add some zero bits for you to the mantissa (unexpected, but well documented)", jo.get( "bug" ).equals( Double.valueOf( 3.1d ) ) );
-
- JSONObject inc = new JSONObject();
- inc.put( "bug", Float.valueOf( 3.1f ) ); // This will put in instance of Float into JSONObject, i.e. call put( String key, Object value )
- assertTrue( "Everything is ok here!", inc.get( "bug" ) instanceof Float );
- inc.increment( "bug" ); // after adding 1, increment will call put( String key, double value ) with implicit and "buggy" type-cast from float to double!
- // this.put(key, (Float) value + 1);
- // 1. The (Object)value will be typecasted to (Float)value since it is an instanceof Float actually nothing is done.
- // 2. Float instance will be autoboxed into float because the + operator will work on primitives not Objects!
- // 3. A float+float operation will be performed and results into a float primitive.
- // 4. There is no method that matches the signature put( String key, float value), java-compiler will choose the method
- // put( String key, double value) and does an implicit type-cast(!) by appending zero-bits to the mantissa
- assertTrue( "JSONObject increment converts Float to Double", jo.get( "bug" ) instanceof Float );
- // correct implementation (with change of behavior) would be:
- // this.put(key, new Float((Float) value + 1));
- // Probably it would be better to deprecate the method and remove some day, while convenient processing the "payload" is not
- // really in the scope of a JSON-library (IMHO.)
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject, inc
- )));
- }
-
- /**
- * Exercise JSONObject numberToString() method
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectNumberToString() {
- String str;
- Double dVal;
- Integer iVal = 1;
- str = JSONObject.numberToString(iVal);
- assertTrue("expected "+iVal+" actual "+str, iVal.toString().equals(str));
- dVal = 12.34;
- str = JSONObject.numberToString(dVal);
- assertTrue("expected "+dVal+" actual "+str, dVal.toString().equals(str));
- dVal = 12.34e27;
- str = JSONObject.numberToString(dVal);
- assertTrue("expected "+dVal+" actual "+str, dVal.toString().equals(str));
- // trailing .0 is truncated, so it doesn't quite match toString()
- dVal = 5000000.0000000;
- str = JSONObject.numberToString(dVal);
- assertTrue("expected 5000000 actual "+str, str.equals("5000000"));
- }
-
- /**
- * Exercise JSONObject put() and similar() methods
- */
- @SuppressWarnings("boxing")
- @Test
- public void jsonObjectPut() {
- String expectedStr =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"arrayKey\":[0,1,2],"+
- "\"objectKey\":{"+
- "\"myKey1\":\"myVal1\","+
- "\"myKey2\":\"myVal2\","+
- "\"myKey3\":\"myVal3\","+
- "\"myKey4\":\"myVal4\""+
- "}"+
- "}";
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("trueKey", true);
- jsonObject.put("falseKey", false);
- Integer [] intArray = { 0, 1, 2 };
- jsonObject.put("arrayKey", Arrays.asList(intArray));
- Map myMap = new HashMap();
- myMap.put("myKey1", "myVal1");
- myMap.put("myKey2", "myVal2");
- myMap.put("myKey3", "myVal3");
- myMap.put("myKey4", "myVal4");
- jsonObject.put("objectKey", myMap);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 4 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 4);
- assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueKey")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseKey")));
- assertTrue("expected 3 arrayKey items", ((List>)(JsonPath.read(doc, "$.arrayKey"))).size() == 3);
- assertTrue("expected 0", Integer.valueOf(0).equals(jsonObject.query("/arrayKey/0")));
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonObject.query("/arrayKey/1")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/arrayKey/2")));
- assertTrue("expected 4 objectKey items", ((Map,?>)(JsonPath.read(doc, "$.objectKey"))).size() == 4);
- assertTrue("expected myVal1", "myVal1".equals(jsonObject.query("/objectKey/myKey1")));
- assertTrue("expected myVal2", "myVal2".equals(jsonObject.query("/objectKey/myKey2")));
- assertTrue("expected myVal3", "myVal3".equals(jsonObject.query("/objectKey/myKey3")));
- assertTrue("expected myVal4", "myVal4".equals(jsonObject.query("/objectKey/myKey4")));
-
- jsonObject.remove("trueKey");
- JSONObject expectedJsonObject = new JSONObject(expectedStr);
- assertTrue("unequal jsonObjects should not be similar",
- !jsonObject.similar(expectedJsonObject));
- assertTrue("jsonObject should not be similar to jsonArray",
- !jsonObject.similar(new JSONArray()));
-
- String aCompareValueStr = "{\"a\":\"aval\",\"b\":true}";
- String bCompareValueStr = "{\"a\":\"notAval\",\"b\":true}";
- JSONObject aCompareValueJsonObject = new JSONObject(aCompareValueStr);
- JSONObject bCompareValueJsonObject = new JSONObject(bCompareValueStr);
- assertTrue("different values should not be similar",
- !aCompareValueJsonObject.similar(bCompareValueJsonObject));
-
- String aCompareObjectStr = "{\"a\":\"aval\",\"b\":{}}";
- String bCompareObjectStr = "{\"a\":\"aval\",\"b\":true}";
- JSONObject aCompareObjectJsonObject = new JSONObject(aCompareObjectStr);
- JSONObject bCompareObjectJsonObject = new JSONObject(bCompareObjectStr);
- assertTrue("different nested JSONObjects should not be similar",
- !aCompareObjectJsonObject.similar(bCompareObjectJsonObject));
-
- String aCompareArrayStr = "{\"a\":\"aval\",\"b\":[]}";
- String bCompareArrayStr = "{\"a\":\"aval\",\"b\":true}";
- JSONObject aCompareArrayJsonObject = new JSONObject(aCompareArrayStr);
- JSONObject bCompareArrayJsonObject = new JSONObject(bCompareArrayStr);
- assertTrue("different nested JSONArrays should not be similar",
- !aCompareArrayJsonObject.similar(bCompareArrayJsonObject));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject, expectedJsonObject, aCompareValueJsonObject,
- aCompareArrayJsonObject, aCompareObjectJsonObject, aCompareArrayJsonObject,
- bCompareValueJsonObject, bCompareArrayJsonObject, bCompareObjectJsonObject,
- bCompareArrayJsonObject
- )));
- }
-
- /**
- * Exercise JSONObject toString() method
- */
- @Test
- public void jsonObjectToString() {
- String str =
- "{"+
- "\"trueKey\":true,"+
- "\"falseKey\":false,"+
- "\"arrayKey\":[0,1,2],"+
- "\"objectKey\":{"+
- "\"myKey1\":\"myVal1\","+
- "\"myKey2\":\"myVal2\","+
- "\"myKey3\":\"myVal3\","+
- "\"myKey4\":\"myVal4\""+
- "}"+
- "}";
- JSONObject jsonObject = new JSONObject(str);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 4 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 4);
- assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueKey")));
- assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseKey")));
- assertTrue("expected 3 arrayKey items", ((List>)(JsonPath.read(doc, "$.arrayKey"))).size() == 3);
- assertTrue("expected 0", Integer.valueOf(0).equals(jsonObject.query("/arrayKey/0")));
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonObject.query("/arrayKey/1")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/arrayKey/2")));
- assertTrue("expected 4 objectKey items", ((Map,?>)(JsonPath.read(doc, "$.objectKey"))).size() == 4);
- assertTrue("expected myVal1", "myVal1".equals(jsonObject.query("/objectKey/myKey1")));
- assertTrue("expected myVal2", "myVal2".equals(jsonObject.query("/objectKey/myKey2")));
- assertTrue("expected myVal3", "myVal3".equals(jsonObject.query("/objectKey/myKey3")));
- assertTrue("expected myVal4", "myVal4".equals(jsonObject.query("/objectKey/myKey4")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise JSONObject toString() method with various indent levels.
- */
- @Test
- public void jsonObjectToStringIndent() {
- String jsonObject0Str =
- "{"+
- "\"key1\":" +
- "[1,2," +
- "{\"key3\":true}" +
- "],"+
- "\"key2\":" +
- "{\"key1\":\"val1\",\"key2\":" +
- "{\"key2\":\"val2\"}" +
- "},"+
- "\"key3\":" +
- "[" +
- "[1,2.1]" +
- "," +
- "[null]" +
- "]"+
- "}";
-
- String jsonObject1Str =
- "{\n" +
- " \"key1\": [\n" +
- " 1,\n" +
- " 2,\n" +
- " {\"key3\": true}\n" +
- " ],\n" +
- " \"key2\": {\n" +
- " \"key1\": \"val1\",\n" +
- " \"key2\": {\"key2\": \"val2\"}\n" +
- " },\n" +
- " \"key3\": [\n" +
- " [\n" +
- " 1,\n" +
- " 2.1\n" +
- " ],\n" +
- " [null]\n" +
- " ]\n" +
- "}";
- String jsonObject4Str =
- "{\n" +
- " \"key1\": [\n" +
- " 1,\n" +
- " 2,\n" +
- " {\"key3\": true}\n" +
- " ],\n" +
- " \"key2\": {\n" +
- " \"key1\": \"val1\",\n" +
- " \"key2\": {\"key2\": \"val2\"}\n" +
- " },\n" +
- " \"key3\": [\n" +
- " [\n" +
- " 1,\n" +
- " 2.1\n" +
- " ],\n" +
- " [null]\n" +
- " ]\n" +
- "}";
- JSONObject jsonObject = new JSONObject(jsonObject0Str);
- // contents are tested in other methods, in this case just validate the spacing by
- // checking length
- assertEquals("toString() length",jsonObject0Str.length(), jsonObject.toString().length());
- assertEquals("toString(0) length",jsonObject0Str.length(), jsonObject.toString(0).length());
- assertEquals("toString(1) length",jsonObject1Str.length(), jsonObject.toString(1).length());
- assertEquals("toString(4) length",jsonObject4Str.length(), jsonObject.toString(4).length());
-
- JSONObject jo = new JSONObject().put("TABLE", new JSONObject().put("yhoo", new JSONObject()));
- assertEquals("toString(2)","{\"TABLE\": {\"yhoo\": {}}}", jo.toString(2));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject, jo
- )));
- }
-
- /**
- * Explores how JSONObject handles maps. Insert a string/string map
- * as a value in a JSONObject. It will remain a map. Convert the
- * JSONObject to string, then create a new JSONObject from the string.
- * In the new JSONObject, the value will be stored as a nested JSONObject.
- * Confirm that map and nested JSONObject have the same contents.
- */
- @Test
- public void jsonObjectToStringSuppressWarningOnCastToMap() {
- JSONObject jsonObject = new JSONObject();
- Map map = new HashMap<>();
- map.put("abc", "def");
- jsonObject.put("key", map);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 1 key item", ((Map,?>)(JsonPath.read(doc, "$.key"))).size() == 1);
- assertTrue("expected def", "def".equals(jsonObject.query("/key/abc")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Explores how JSONObject handles collections. Insert a string collection
- * as a value in a JSONObject. It will remain a collection. Convert the
- * JSONObject to string, then create a new JSONObject from the string.
- * In the new JSONObject, the value will be stored as a nested JSONArray.
- * Confirm that collection and nested JSONArray have the same contents.
- */
- @Test
- public void jsonObjectToStringSuppressWarningOnCastToCollection() {
- JSONObject jsonObject = new JSONObject();
- Collection collection = new ArrayList();
- collection.add("abc");
- // ArrayList will be added as an object
- jsonObject.put("key", collection);
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
- assertTrue("expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected 1 key item", ((List>)(JsonPath.read(doc, "$.key"))).size() == 1);
- assertTrue("expected abc", "abc".equals(jsonObject.query("/key/0")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercises the JSONObject.valueToString() method for various types
- */
- @Test
- public void valueToString() {
-
- assertTrue("null valueToString() incorrect",
- "null".equals(JSONObject.valueToString(null)));
- MyJsonString jsonString = new MyJsonString();
- assertTrue("jsonstring valueToString() incorrect",
- "my string".equals(JSONObject.valueToString(jsonString)));
- assertTrue("boolean valueToString() incorrect",
- "true".equals(JSONObject.valueToString(Boolean.TRUE)));
- assertTrue("non-numeric double",
- "null".equals(JSONObject.doubleToString(Double.POSITIVE_INFINITY)));
- String jsonObjectStr =
- "{"+
- "\"key1\":\"val1\","+
- "\"key2\":\"val2\","+
- "\"key3\":\"val3\""+
- "}";
- JSONObject jsonObject = new JSONObject(jsonObjectStr);
- assertTrue("jsonObject valueToString() incorrect",
- new JSONObject(JSONObject.valueToString(jsonObject))
- .similar(new JSONObject(jsonObject.toString()))
- );
- String jsonArrayStr =
- "[1,2,3]";
- JSONArray jsonArray = new JSONArray(jsonArrayStr);
- assertTrue("jsonArray valueToString() incorrect",
- JSONObject.valueToString(jsonArray).equals(jsonArray.toString()));
- Map map = new HashMap();
- map.put("key1", "val1");
- map.put("key2", "val2");
- map.put("key3", "val3");
- assertTrue("map valueToString() incorrect",
- new JSONObject(jsonObject.toString())
- .similar(new JSONObject(JSONObject.valueToString(map))));
- Collection collection = new ArrayList();
- collection.add(Integer.valueOf(1));
- collection.add(Integer.valueOf(2));
- collection.add(Integer.valueOf(3));
- assertTrue("collection valueToString() expected: "+
- jsonArray.toString()+ " actual: "+
- JSONObject.valueToString(collection),
- jsonArray.toString().equals(JSONObject.valueToString(collection)));
- Integer[] array = { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3) };
- assertTrue("array valueToString() incorrect",
- jsonArray.toString().equals(JSONObject.valueToString(array)));
- Util.checkJSONObjectMaps(jsonObject);
- Util.checkJSONArrayMaps(jsonArray, jsonObject.getMapType());
- }
-
- /**
- * Confirm that https://github.com/douglascrockford/JSON-java/issues/167 is fixed.
- * The following code was throwing a ClassCastException in the
- * JSONObject(Map) constructor
- */
- @SuppressWarnings("boxing")
- @Test
- public void valueToStringConfirmException() {
- Map myMap = new HashMap();
- myMap.put(1, "myValue");
- // this is the test, it should not throw an exception
- String str = JSONObject.valueToString(myMap);
- // confirm result, just in case
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(str);
- assertTrue("expected 1 top level item", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 1);
- assertTrue("expected myValue", "myValue".equals(JsonPath.read(doc, "$.1")));
- }
-
- /**
- * Exercise the JSONObject wrap() method. Sometimes wrap() will change
- * the object being wrapped, other times not. The purpose of wrap() is
- * to ensure the value is packaged in a way that is compatible with how
- * a JSONObject value or JSONArray value is supposed to be stored.
- */
- @Test
- public void wrapObject() {
- // wrap(null) returns NULL
- assertTrue("null wrap() incorrect",
- JSONObject.NULL == JSONObject.wrap(null));
-
- // wrap(Integer) returns Integer
- Integer in = Integer.valueOf(1);
- assertTrue("Integer wrap() incorrect",
- in == JSONObject.wrap(in));
-
- /**
- * This test is to document the preferred behavior if BigDecimal is
- * supported. Previously bd returned as a string, since it
- * is recognized as being a Java package class. Now with explicit
- * support for big numbers, it remains a BigDecimal
- */
- Object bdWrap = JSONObject.wrap(BigDecimal.ONE);
- assertTrue("BigDecimal.ONE evaluates to ONE",
- bdWrap.equals(BigDecimal.ONE));
-
- // wrap JSONObject returns JSONObject
- String jsonObjectStr =
- "{"+
- "\"key1\":\"val1\","+
- "\"key2\":\"val2\","+
- "\"key3\":\"val3\""+
- "}";
- JSONObject jsonObject = new JSONObject(jsonObjectStr);
- assertTrue("JSONObject wrap() incorrect",
- jsonObject == JSONObject.wrap(jsonObject));
-
- // wrap collection returns JSONArray
- Collection collection = new ArrayList();
- collection.add(Integer.valueOf(1));
- collection.add(Integer.valueOf(2));
- collection.add(Integer.valueOf(3));
- JSONArray jsonArray = (JSONArray) (JSONObject.wrap(collection));
-
- // validate JSON
- Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 3 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/1")));
- assertTrue("expected 3", Integer.valueOf(3).equals(jsonArray.query("/2")));
-
- // wrap Array returns JSONArray
- Integer[] array = { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3) };
- JSONArray integerArrayJsonArray = (JSONArray)(JSONObject.wrap(array));
-
- // validate JSON
- doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
- assertTrue("expected 3 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/1")));
- assertTrue("expected 3", Integer.valueOf(3).equals(jsonArray.query("/2")));
-
- // validate JSON
- doc = Configuration.defaultConfiguration().jsonProvider().parse(integerArrayJsonArray.toString());
- assertTrue("expected 3 top level items", ((List>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/0")));
- assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/1")));
- assertTrue("expected 3", Integer.valueOf(3).equals(jsonArray.query("/2")));
-
- // wrap map returns JSONObject
- Map map = new HashMap();
- map.put("key1", "val1");
- map.put("key2", "val2");
- map.put("key3", "val3");
- JSONObject mapJsonObject = (JSONObject) (JSONObject.wrap(map));
-
- // validate JSON
- doc = Configuration.defaultConfiguration().jsonProvider().parse(mapJsonObject.toString());
- assertTrue("expected 3 top level items", ((Map,?>)(JsonPath.read(doc, "$"))).size() == 3);
- assertTrue("expected val1", "val1".equals(mapJsonObject.query("/key1")));
- assertTrue("expected val2", "val2".equals(mapJsonObject.query("/key2")));
- assertTrue("expected val3", "val3".equals(mapJsonObject.query("/key3")));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObject, mapJsonObject
- )));
- Util.checkJSONArrayMaps(jsonArray, jsonObject.getMapType());
- Util.checkJSONArrayMaps(integerArrayJsonArray, jsonObject.getMapType());
- }
-
-
- /**
- * RFC 7159 defines control characters to be U+0000 through U+001F. This test verifies that the parser is checking for these in expected ways.
- */
- @Test
- public void jsonObjectParseControlCharacters(){
- for(int i = 0;i<=0x001f;i++){
- final String charString = String.valueOf((char)i);
- final String source = "{\"key\":\""+charString+"\"}";
- try {
- JSONObject jo = new JSONObject(source);
- assertTrue("Expected "+charString+"("+i+") in the JSON Object but did not find it.",charString.equals(jo.getString("key")));
- Util.checkJSONObjectMaps(jo);
- } catch (JSONException ex) {
- assertTrue("Only \\0 (U+0000), \\n (U+000A), and \\r (U+000D) should cause an error. Instead "+charString+"("+i+") caused an error",
- i=='\0' || i=='\n' || i=='\r'
- );
- }
- }
- }
-
- @Test
- public void jsonObjectParseControlCharacterEOFAssertExceptionMessage(){
- char c = '\0';
- final String source = "{\"key\":\"" + c + "\"}";
- try {
- JSONObject jo = new JSONObject(source);
- fail("JSONException should be thrown");
- } catch (JSONException ex) {
- assertEquals("Unterminated string. " + "Character with int code 0" +
- " is not allowed within a quoted string. at 8 [character 9 line 1]", ex.getMessage());
- }
- }
-
- @Test
- public void jsonObjectParseControlCharacterNewLineAssertExceptionMessage(){
- char[] chars = {'\n', '\r'};
- for( char c : chars) {
- final String source = "{\"key\":\"" + c + "\"}";
- try {
- JSONObject jo = new JSONObject(source);
- fail("JSONException should be thrown");
- } catch (JSONException ex) {
- assertEquals("Unterminated string. " + "Character with int code " + (int) c +
- " is not allowed within a quoted string. at 9 [character 0 line 2]", ex.getMessage());
- }
- }
- }
-
- @Test
- public void jsonObjectParseUTF8EncodingAssertExceptionMessage(){
- String c = "\\u123x";
- final String source = "{\"key\":\"" + c + "\"}";
- try {
- JSONObject jo = new JSONObject(source);
- fail("JSONException should be thrown");
- } catch (JSONException ex) {
- assertEquals("Illegal escape. \\u must be followed by a 4 digit hexadecimal number. " +
- "\\123x is not valid. at 14 [character 15 line 1]", ex.getMessage());
- }
- }
-
- @Test
- public void jsonObjectParseIllegalEscapeAssertExceptionMessage(){
- String c = "\\x";
- final String source = "{\"key\":\"" + c + "\"}";
- try {
- JSONObject jo = new JSONObject(source);
- fail("JSONException should be thrown");
- } catch (JSONException ex) {
- assertEquals("Illegal escape. Escape sequence " + c + " is not valid." +
- " at 10 [character 11 line 1]", ex.getMessage());
- }
- }
-
- @Test
- public void parsingErrorTrailingCurlyBrace () {
- try {
- // does not end with '}'
- String str = "{";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "A JSONObject text must end with '}' at 1 [character 2 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorInitialCurlyBrace() {
- try {
- // does not start with '{'
- String str = "abc";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "A JSONObject text must begin with '{' at 1 [character 2 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorNoColon() {
- try {
- // key with no ':'
- String str = "{\"myKey\" = true}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Expected a ':' after a key at 10 [character 11 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorNoCommaSeparator() {
- try {
- // entries with no ',' separator
- String str = "{\"myKey\":true \"myOtherKey\":false}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Expected a ',' or '}' at 15 [character 16 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorKeyIsNestedMap() {
- try {
- // key is a nested map
- String str = "{{\"foo\": \"bar\"}: \"baz\"}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Missing value at 1 [character 2 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorKeyIsNestedArrayWithMap() {
- try {
- // key is a nested array containing a map
- String str = "{\"a\": 1, [{\"foo\": \"bar\"}]: \"baz\"}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Missing value at 9 [character 10 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorKeyContainsCurlyBrace() {
- try {
- // key contains }
- String str = "{foo}: 2}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
-// assertEquals("Expecting an exception message",
-// "Expected a ':' after a key at 5 [character 6 line 1]",
-// e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorKeyContainsSquareBrace() {
- try {
- // key contains ]
- String str = "{foo]: 2}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
-// assertEquals("Expecting an exception message",
-// "Expected a ':' after a key at 5 [character 6 line 1]",
-// e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorKeyContainsBinaryZero() {
- try {
- // \0 after ,
- String str = "{\"myKey\":true, \0\"myOtherKey\":false}";
- assertNull("Expected an exception", new JSONObject(str));
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "A JSONObject text must end with '}' at 15 [character 16 line 1]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorAppendToWrongValue() {
- try {
- // append to wrong value
- String str = "{\"myKey\":true, \"myOtherKey\":false}";
- JSONObject jsonObject = new JSONObject(str);
- jsonObject.append("myKey", "hello");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "JSONObject[\"myKey\"] is not a JSONArray (null).",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorIncrementWrongValue() {
- try {
- // increment wrong value
- String str = "{\"myKey\":true, \"myOtherKey\":false}";
- JSONObject jsonObject = new JSONObject(str);
- jsonObject.increment("myKey");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Unable to increment [\"myKey\"].",
- e.getMessage());
- }
- }
- @Test
- public void parsingErrorInvalidKey() {
- try {
- // invalid key
- String str = "{\"myKey\":true, \"myOtherKey\":false}";
- JSONObject jsonObject = new JSONObject(str);
- jsonObject.get(null);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Null key.",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorNumberToString() {
- try {
- // invalid numberToString()
- JSONObject.numberToString((Number) null);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an exception message",
- "Null pointer",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorPutOnceDuplicateKey() {
- try {
- // multiple putOnce key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.putOnce("hello", "world");
- jsonObject.putOnce("hello", "world!");
- fail("Expected an exception");
- } catch (JSONException e) {
- assertTrue("", true);
- }
- }
-
- @Test
- public void parsingErrorInvalidDouble() {
- try {
- // test validity of invalid double
- JSONObject.testValidity(Double.NaN);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertTrue("", true);
- }
- }
-
- @Test
- public void parsingErrorInvalidFloat() {
- try {
- // test validity of invalid float
- JSONObject.testValidity(Float.NEGATIVE_INFINITY);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertTrue("", true);
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyException() {
- try {
- // test exception message when including a duplicate key (level 0)
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr03\":\"value-04\"\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr03\" at 90 [character 13 line 5]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorNestedDuplicateKeyException() {
- try {
- // test exception message when including a duplicate key (level 0) holding an object
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr03\": {"
- + " \"attr04-01\":\"value-04-01\",n"
- + " \"attr04-02\":\"value-04-02\",n"
- + " \"attr04-03\":\"value-04-03\"n"
- + " }\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr03\" at 90 [character 13 line 5]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorNestedDuplicateKeyWithArrayException() {
- try {
- // test exception message when including a duplicate key (level 0) holding an array
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr03\": [\n"
- + " {"
- + " \"attr04-01\":\"value-04-01\",n"
- + " \"attr04-02\":\"value-04-02\",n"
- + " \"attr04-03\":\"value-04-03\"n"
- + " }\n"
- + " ]\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr03\" at 90 [character 13 line 5]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyWithinNestedDictExceptionMessage() {
- try {
- // test exception message when including a duplicate key (level 1)
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr04\": {\n"
- + " \"attr04-01\":\"value04-01\",\n"
- + " \"attr04-02\":\"value04-02\",\n"
- + " \"attr04-03\":\"value04-03\",\n"
- + " \"attr04-03\":\"value04-04\"\n"
- + " }\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr04-03\" at 215 [character 20 line 9]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyDoubleNestedDictExceptionMessage() {
- try {
- // test exception message when including a duplicate key (level 1) holding an
- // object
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr04\": {\n"
- + " \"attr04-01\":\"value04-01\",\n"
- + " \"attr04-02\":\"value04-02\",\n"
- + " \"attr04-03\":\"value04-03\",\n"
- + " \"attr04-03\": {\n"
- + " \"attr04-04-01\":\"value04-04-01\",\n"
- + " \"attr04-04-02\":\"value04-04-02\",\n"
- + " \"attr04-04-03\":\"value04-04-03\",\n"
- + " }\n"
- + " }\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr04-03\" at 215 [character 20 line 9]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyNestedWithArrayExceptionMessage() {
- try {
- // test exception message when including a duplicate key (level 1) holding an
- // array
- String str = "{\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\",\n"
- + " \"attr03\":\"value-03\",\n"
- + " \"attr04\": {\n"
- + " \"attr04-01\":\"value04-01\",\n"
- + " \"attr04-02\":\"value04-02\",\n"
- + " \"attr04-03\":\"value04-03\",\n"
- + " \"attr04-03\": [\n"
- + " {\n"
- + " \"attr04-04-01\":\"value04-04-01\",\n"
- + " \"attr04-04-02\":\"value04-04-02\",\n"
- + " \"attr04-04-03\":\"value04-04-03\",\n"
- + " }\n"
- + " ]\n"
- + " }\n"
- + "}";
- new JSONObject(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr04-03\" at 215 [character 20 line 9]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyWithinArrayExceptionMessage() {
- try {
- // test exception message when including a duplicate key in object (level 0)
- // within an array
- String str = "[\n"
- + " {\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\":\"value-02\"\n"
- + " },\n"
- + " {\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr01\":\"value-02\"\n"
- + " }\n"
- + "]";
- new JSONArray(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr01\" at 124 [character 17 line 8]",
- e.getMessage());
- }
- }
-
- @Test
- public void parsingErrorDuplicateKeyDoubleNestedWithinArrayExceptionMessage() {
- try {
- // test exception message when including a duplicate key in object (level 1)
- // within an array
- String str = "[\n"
- + " {\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\": {\n"
- + " \"attr02-01\":\"value-02-01\",\n"
- + " \"attr02-02\":\"value-02-02\"\n"
- + " }\n"
- + " },\n"
- + " {\n"
- + " \"attr01\":\"value-01\",\n"
- + " \"attr02\": {\n"
- + " \"attr02-01\":\"value-02-01\",\n"
- + " \"attr02-01\":\"value-02-02\"\n"
- + " }\n"
- + " }\n"
- + "]";
- new JSONArray(str);
- fail("Expected an exception");
- } catch (JSONException e) {
- assertEquals("Expecting an expection message",
- "Duplicate key \"attr02-01\" at 269 [character 24 line 13]",
- e.getMessage());
- }
- }
-
- /**
- * Confirm behavior when putOnce() is called with null parameters
- */
- @Test
- public void jsonObjectPutOnceNull() {
- JSONObject jsonObject = new JSONObject();
- jsonObject.putOnce(null, null);
- assertTrue("jsonObject should be empty", jsonObject.isEmpty());
- jsonObject.putOnce("", null);
- assertTrue("jsonObject should be empty", jsonObject.isEmpty());
- jsonObject.putOnce(null, "");
- assertTrue("jsonObject should be empty", jsonObject.isEmpty());
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise JSONObject opt(key, default) method.
- */
- @Test
- public void jsonObjectOptDefault() {
-
- String str = "{\"myKey\": \"myval\", \"hiKey\": null}";
- JSONObject jsonObject = new JSONObject(str);
-
- assertTrue("optBigDecimal() should return default BigDecimal",
- BigDecimal.TEN.compareTo(jsonObject.optBigDecimal("myKey", BigDecimal.TEN))==0);
- assertTrue("optBigInteger() should return default BigInteger",
- BigInteger.TEN.compareTo(jsonObject.optBigInteger("myKey",BigInteger.TEN ))==0);
- assertTrue("optBoolean() should return default boolean",
- jsonObject.optBoolean("myKey", true));
- assertTrue("optBooleanObject() should return default Boolean",
- jsonObject.optBooleanObject("myKey", true));
- assertTrue("optInt() should return default int",
- 42 == jsonObject.optInt("myKey", 42));
- assertTrue("optIntegerObject() should return default Integer",
- Integer.valueOf(42).equals(jsonObject.optIntegerObject("myKey", 42)));
- assertTrue("optEnum() should return default Enum",
- MyEnum.VAL1.equals(jsonObject.optEnum(MyEnum.class, "myKey", MyEnum.VAL1)));
- assertTrue("optJSONArray() should return null ",
- null==jsonObject.optJSONArray("myKey"));
- assertTrue("optJSONArray() should return default JSONArray",
- "value".equals(jsonObject.optJSONArray("myKey", new JSONArray("[\"value\"]")).getString(0)));
- assertTrue("optJSONObject() should return default JSONObject ",
- jsonObject.optJSONObject("myKey", new JSONObject("{\"testKey\":\"testValue\"}")).getString("testKey").equals("testValue"));
- assertTrue("optLong() should return default long",
- 42l == jsonObject.optLong("myKey", 42l));
- assertTrue("optLongObject() should return default Long",
- Long.valueOf(42l).equals(jsonObject.optLongObject("myKey", 42l)));
- assertTrue("optDouble() should return default double",
- 42.3d == jsonObject.optDouble("myKey", 42.3d));
- assertTrue("optDoubleObject() should return default Double",
- Double.valueOf(42.3d).equals(jsonObject.optDoubleObject("myKey", 42.3d)));
- assertTrue("optFloat() should return default float",
- 42.3f == jsonObject.optFloat("myKey", 42.3f));
- assertTrue("optFloatObject() should return default Float",
- Float.valueOf(42.3f).equals(jsonObject.optFloatObject("myKey", 42.3f)));
- assertTrue("optNumber() should return default Number",
- 42l == jsonObject.optNumber("myKey", Long.valueOf(42)).longValue());
- assertTrue("optString() should return default string",
- "hi".equals(jsonObject.optString("hiKey", "hi")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise JSONObject opt(key, default) method when the key doesn't exist.
- */
- @Test
- public void jsonObjectOptNoKey() {
-
- JSONObject jsonObject = new JSONObject();
-
- assertNull(jsonObject.opt(null));
-
- assertTrue("optBigDecimal() should return default BigDecimal",
- BigDecimal.TEN.compareTo(jsonObject.optBigDecimal("myKey", BigDecimal.TEN))==0);
- assertTrue("optBigInteger() should return default BigInteger",
- BigInteger.TEN.compareTo(jsonObject.optBigInteger("myKey",BigInteger.TEN ))==0);
- assertTrue("optBoolean() should return default boolean",
- jsonObject.optBoolean("myKey", true));
- assertTrue("optBooleanObject() should return default Boolean",
- jsonObject.optBooleanObject("myKey", true));
- assertTrue("optInt() should return default int",
- 42 == jsonObject.optInt("myKey", 42));
- assertTrue("optIntegerObject() should return default Integer",
- Integer.valueOf(42).equals(jsonObject.optIntegerObject("myKey", 42)));
- assertTrue("optEnum() should return default Enum",
- MyEnum.VAL1.equals(jsonObject.optEnum(MyEnum.class, "myKey", MyEnum.VAL1)));
- assertTrue("optJSONArray() should return default JSONArray",
- "value".equals(jsonObject.optJSONArray("myKey", new JSONArray("[\"value\"]")).getString(0)));
- assertTrue("optJSONArray() should return null ",
- null==jsonObject.optJSONArray("myKey"));
- assertTrue("optJSONObject() should return default JSONObject ",
- jsonObject.optJSONObject("myKey", new JSONObject("{\"testKey\":\"testValue\"}")).getString("testKey").equals("testValue"));
- assertTrue("optLong() should return default long",
- 42l == jsonObject.optLong("myKey", 42l));
- assertTrue("optLongObject() should return default Long",
- Long.valueOf(42l).equals(jsonObject.optLongObject("myKey", 42l)));
- assertTrue("optDouble() should return default double",
- 42.3d == jsonObject.optDouble("myKey", 42.3d));
- assertTrue("optDoubleObject() should return default Double",
- Double.valueOf(42.3d).equals(jsonObject.optDoubleObject("myKey", 42.3d)));
- assertTrue("optFloat() should return default float",
- 42.3f == jsonObject.optFloat("myKey", 42.3f));
- assertTrue("optFloatObject() should return default Float",
- Float.valueOf(42.3f).equals(jsonObject.optFloatObject("myKey", 42.3f)));
- assertTrue("optNumber() should return default Number",
- 42l == jsonObject.optNumber("myKey", Long.valueOf(42)).longValue());
- assertTrue("optString() should return default string",
- "hi".equals(jsonObject.optString("hiKey", "hi")));
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Verifies that the opt methods properly convert string values.
- */
- @Test
- public void jsonObjectOptStringConversion() {
- JSONObject jo = new JSONObject("{\"int\":\"123\",\"true\":\"true\",\"false\":\"false\"}");
- assertTrue("unexpected optBoolean value",jo.optBoolean("true",false)==true);
- assertTrue("unexpected optBooleanObject value",Boolean.valueOf(true).equals(jo.optBooleanObject("true",false)));
- assertTrue("unexpected optBoolean value",jo.optBoolean("false",true)==false);
- assertTrue("unexpected optBooleanObject value",Boolean.valueOf(false).equals(jo.optBooleanObject("false",true)));
- assertTrue("unexpected optInt value",jo.optInt("int",0)==123);
- assertTrue("unexpected optIntegerObject value",Integer.valueOf(123).equals(jo.optIntegerObject("int",0)));
- assertTrue("unexpected optLong value",jo.optLong("int",0)==123l);
- assertTrue("unexpected optLongObject value",Long.valueOf(123l).equals(jo.optLongObject("int",0L)));
- assertTrue("unexpected optDouble value",jo.optDouble("int",0.0d)==123.0d);
- assertTrue("unexpected optDoubleObject value",Double.valueOf(123.0d).equals(jo.optDoubleObject("int",0.0d)));
- assertTrue("unexpected optFloat value",jo.optFloat("int",0.0f)==123.0f);
- assertTrue("unexpected optFloatObject value",Float.valueOf(123.0f).equals(jo.optFloatObject("int",0.0f)));
- assertTrue("unexpected optBigInteger value",jo.optBigInteger("int",BigInteger.ZERO).compareTo(new BigInteger("123"))==0);
- assertTrue("unexpected optBigDecimal value",jo.optBigDecimal("int",BigDecimal.ZERO).compareTo(new BigDecimal("123"))==0);
- assertTrue("unexpected optBigDecimal value",jo.optBigDecimal("int",BigDecimal.ZERO).compareTo(new BigDecimal("123"))==0);
- assertTrue("unexpected optNumber value",jo.optNumber("int",BigInteger.ZERO).longValue()==123l);
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Verifies that the opt methods properly convert string values to numbers and coerce them consistently.
- */
- @Test
- public void jsonObjectOptCoercion() {
- JSONObject jo = new JSONObject("{\"largeNumberStr\":\"19007199254740993.35481234487103587486413587843213584\"}");
- // currently the parser doesn't recognize BigDecimal, to we have to put it manually
- jo.put("largeNumber", new BigDecimal("19007199254740993.35481234487103587486413587843213584"));
-
- // Test type coercion from larger to smaller
- assertEquals(new BigDecimal("19007199254740993.35481234487103587486413587843213584"), jo.optBigDecimal("largeNumber",null));
- assertEquals(new BigInteger("19007199254740993"), jo.optBigInteger("largeNumber",null));
- assertEquals(1.9007199254740992E16, jo.optDouble("largeNumber"),0.0);
- assertEquals(1.9007199254740992E16, jo.optDoubleObject("largeNumber"),0.0);
- assertEquals(1.90071995E16f, jo.optFloat("largeNumber"),0.0f);
- assertEquals(1.90071995E16f, jo.optFloatObject("largeNumber"),0.0f);
- assertEquals(19007199254740993l, jo.optLong("largeNumber"));
- assertEquals(Long.valueOf(19007199254740993l), jo.optLongObject("largeNumber"));
- assertEquals(1874919425, jo.optInt("largeNumber"));
- assertEquals(Integer.valueOf(1874919425), jo.optIntegerObject("largeNumber"));
-
- // conversion from a string
- assertEquals(new BigDecimal("19007199254740993.35481234487103587486413587843213584"), jo.optBigDecimal("largeNumberStr",null));
- assertEquals(new BigInteger("19007199254740993"), jo.optBigInteger("largeNumberStr",null));
- assertEquals(1.9007199254740992E16, jo.optDouble("largeNumberStr"),0.0);
- assertEquals(1.9007199254740992E16, jo.optDoubleObject("largeNumberStr"),0.0);
- assertEquals(1.90071995E16f, jo.optFloat("largeNumberStr"),0.0f);
- assertEquals(1.90071995E16f, jo.optFloatObject("largeNumberStr"),0.0f);
- assertEquals(19007199254740993l, jo.optLong("largeNumberStr"));
- assertEquals(Long.valueOf(19007199254740993l), jo.optLongObject("largeNumberStr"));
- assertEquals(1874919425, jo.optInt("largeNumberStr"));
- assertEquals(Integer.valueOf(1874919425), jo.optIntegerObject("largeNumberStr"));
-
- // the integer portion of the actual value is larger than a double can hold.
- assertNotEquals((long)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"), jo.optLong("largeNumber"));
- assertNotEquals(Long.valueOf((long)Double.parseDouble("19007199254740993.35481234487103587486413587843213584")), jo.optLongObject("largeNumber"));
- assertNotEquals((int)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"), jo.optInt("largeNumber"));
- assertNotEquals(Integer.valueOf((int)Double.parseDouble("19007199254740993.35481234487103587486413587843213584")), jo.optIntegerObject("largeNumber"));
- assertNotEquals((long)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"), jo.optLong("largeNumberStr"));
- assertNotEquals(Long.valueOf((long)Double.parseDouble("19007199254740993.35481234487103587486413587843213584")), jo.optLongObject("largeNumberStr"));
- assertNotEquals((int)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"), jo.optInt("largeNumberStr"));
- assertNotEquals(Integer.valueOf((int)Double.parseDouble("19007199254740993.35481234487103587486413587843213584")), jo.optIntegerObject("largeNumberStr"));
- assertEquals(19007199254740992l, (long)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"));
- assertEquals(2147483647, (int)Double.parseDouble("19007199254740993.35481234487103587486413587843213584"));
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Verifies that the optBigDecimal method properly converts values to BigDecimal and coerce them consistently.
- */
- @Test
- public void jsonObjectOptBigDecimal() {
- JSONObject jo = new JSONObject().put("int", 123).put("long", 654L)
- .put("float", 1.234f).put("double", 2.345d)
- .put("bigInteger", new BigInteger("1234"))
- .put("bigDecimal", new BigDecimal("1234.56789"))
- .put("nullVal", JSONObject.NULL);
-
- assertEquals(new BigDecimal("123"),jo.optBigDecimal("int", null));
- assertEquals(new BigDecimal("654"),jo.optBigDecimal("long", null));
- assertEquals(new BigDecimal(1.234f),jo.optBigDecimal("float", null));
- assertEquals(new BigDecimal(2.345d),jo.optBigDecimal("double", null));
- assertEquals(new BigDecimal("1234"),jo.optBigDecimal("bigInteger", null));
- assertEquals(new BigDecimal("1234.56789"),jo.optBigDecimal("bigDecimal", null));
- assertNull(jo.optBigDecimal("nullVal", null));
- assertEquals(jo.optBigDecimal("float", null),jo.getBigDecimal("float"));
- assertEquals(jo.optBigDecimal("double", null),jo.getBigDecimal("double"));
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Verifies that the optBigDecimal method properly converts values to BigDecimal and coerce them consistently.
- */
- @Test
- public void jsonObjectOptBigInteger() {
- JSONObject jo = new JSONObject().put("int", 123).put("long", 654L)
- .put("float", 1.234f).put("double", 2.345d)
- .put("bigInteger", new BigInteger("1234"))
- .put("bigDecimal", new BigDecimal("1234.56789"))
- .put("nullVal", JSONObject.NULL);
-
- assertEquals(new BigInteger("123"),jo.optBigInteger("int", null));
- assertEquals(new BigInteger("654"),jo.optBigInteger("long", null));
- assertEquals(new BigInteger("1"),jo.optBigInteger("float", null));
- assertEquals(new BigInteger("2"),jo.optBigInteger("double", null));
- assertEquals(new BigInteger("1234"),jo.optBigInteger("bigInteger", null));
- assertEquals(new BigInteger("1234"),jo.optBigInteger("bigDecimal", null));
- assertNull(jo.optBigDecimal("nullVal", null));
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Confirm behavior when JSONObject put(key, null object) is called
- */
- @Test
- public void jsonObjectputNull() {
-
- // put null should remove the item.
- String str = "{\"myKey\": \"myval\"}";
- JSONObject jsonObjectRemove = new JSONObject(str);
- jsonObjectRemove.remove("myKey");
- assertTrue("jsonObject should be empty", jsonObjectRemove.isEmpty());
-
- JSONObject jsonObjectPutNull = new JSONObject(str);
- jsonObjectPutNull.put("myKey", (Object) null);
- assertTrue("jsonObject should be empty", jsonObjectPutNull.isEmpty());
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObjectRemove, jsonObjectPutNull
- )));
- }
-
- /**
- * Exercise JSONObject quote() method
- * This purpose of quote() is to ensure that for strings with embedded
- * quotes, the quotes are properly escaped.
- */
- @Test
- public void jsonObjectQuote() {
- String str;
- str = "";
- String quotedStr;
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped quotes, found "+quotedStr,
- "\"\"".equals(quotedStr));
- str = "\"\"";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped quotes, found "+quotedStr,
- "\"\\\"\\\"\"".equals(quotedStr));
- str = "";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped frontslash, found "+quotedStr,
- "\"<\\/\"".equals(quotedStr));
- str = "AB\bC";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped backspace, found "+quotedStr,
- "\"AB\\bC\"".equals(quotedStr));
- str = "ABC\n";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped newline, found "+quotedStr,
- "\"ABC\\n\"".equals(quotedStr));
- str = "AB\fC";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped formfeed, found "+quotedStr,
- "\"AB\\fC\"".equals(quotedStr));
- str = "\r";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped return, found "+quotedStr,
- "\"\\r\"".equals(quotedStr));
- str = "\u1234\u0088";
- quotedStr = JSONObject.quote(str);
- assertTrue("quote() expected escaped unicode, found "+quotedStr,
- "\"\u1234\\u0088\"".equals(quotedStr));
- }
-
- /**
- * Confirm behavior when JSONObject stringToValue() is called for an
- * empty string
- */
- @Test
- public void stringToValue() {
- String str = "";
- String valueStr = (String)(JSONObject.stringToValue(str));
- assertTrue("stringToValue() expected empty String, found "+valueStr,
- "".equals(valueStr));
- }
-
- /**
- * Confirm behavior when toJSONArray is called with a null value
- */
- @Test
- public void toJSONArray() {
- assertTrue("toJSONArray() with null names should be null",
- null == new JSONObject().toJSONArray(null));
- }
-
- /**
- * Exercise the JSONObject write() method
- */
- @Test
- public void write() throws IOException {
- String str = "{\"key1\":\"value1\",\"key2\":[1,2,3]}";
- String expectedStr = str;
- JSONObject jsonObject = new JSONObject(str);
- StringWriter stringWriter = new StringWriter();
- try {
- String actualStr = jsonObject.write(stringWriter).toString();
- // key order may change. verify length and individual key content
- assertEquals("length", expectedStr.length(), actualStr.length());
- assertTrue("key1", actualStr.contains("\"key1\":\"value1\""));
- assertTrue("key2", actualStr.contains("\"key2\":[1,2,3]"));
- } finally {
- stringWriter.close();
- }
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Confirms that exceptions thrown when writing values are wrapped properly.
- */
- @Test
- public void testJSONWriterException() {
- final JSONObject jsonObject = new JSONObject();
-
- jsonObject.put("someKey",new BrokenToString());
-
- // test single element JSONObject
- StringWriter writer = new StringWriter();
- try {
- jsonObject.write(writer).toString();
- fail("Expected an exception, got a String value");
- } catch (JSONException e) {
- assertEquals("Unable to write JSONObject value for key: someKey", e.getMessage());
- } catch(Exception e) {
- fail("Expected JSONException");
- } finally {
- try {
- writer.close();
- } catch (Exception e) {}
- }
-
- //test multiElement
- jsonObject.put("somethingElse", "a value");
-
- writer = new StringWriter();
- try {
- jsonObject.write(writer).toString();
- fail("Expected an exception, got a String value");
- } catch (JSONException e) {
- assertEquals("Unable to write JSONObject value for key: someKey", e.getMessage());
- } catch(Exception e) {
- fail("Expected JSONException");
- } finally {
- try {
- writer.close();
- } catch (Exception e) {}
- }
-
- // test a more complex object
- writer = new StringWriter();
- try {
- new JSONObject()
- .put("somethingElse", "a value")
- .put("someKey", new JSONArray()
- .put(new JSONObject().put("key1", new BrokenToString())))
- .write(writer).toString();
- fail("Expected an exception, got a String value");
- } catch (JSONException e) {
- assertEquals("Unable to write JSONObject value for key: someKey", e.getMessage());
- } catch(Exception e) {
- fail("Expected JSONException");
- } finally {
- try {
- writer.close();
- } catch (Exception e) {}
- }
-
- // test a more slightly complex object
- writer = new StringWriter();
- try {
- new JSONObject()
- .put("somethingElse", "a value")
- .put("someKey", new JSONArray()
- .put(new JSONObject().put("key1", new BrokenToString()))
- .put(12345)
- )
- .write(writer).toString();
- fail("Expected an exception, got a String value");
- } catch (JSONException e) {
- assertEquals("Unable to write JSONObject value for key: someKey", e.getMessage());
- } catch(Exception e) {
- fail("Expected JSONException");
- } finally {
- try {
- writer.close();
- } catch (Exception e) {}
- }
- Util.checkJSONObjectMaps(jsonObject);
- }
-
-
- /**
- * Exercise the JSONObject write() method
- */
-/*
- @Test
- public void writeAppendable() {
- String str = "{\"key1\":\"value1\",\"key2\":[1,2,3]}";
- String expectedStr = str;
- JSONObject jsonObject = new JSONObject(str);
- StringBuilder stringBuilder = new StringBuilder();
- Appendable appendable = jsonObject.write(stringBuilder);
- String actualStr = appendable.toString();
- assertTrue("write() expected " +expectedStr+
- " but found " +actualStr,
- expectedStr.equals(actualStr));
- }
-*/
-
- /**
- * Exercise the JSONObject write(Writer, int, int) method
- */
- @Test
- public void write3Param() throws IOException {
- String str0 = "{\"key1\":\"value1\",\"key2\":[1,false,3.14]}";
- String str2 =
- "{\n" +
- " \"key1\": \"value1\",\n" +
- " \"key2\": [\n" +
- " 1,\n" +
- " false,\n" +
- " 3.14\n" +
- " ]\n" +
- " }";
- JSONObject jsonObject = new JSONObject(str0);
- StringWriter stringWriter = new StringWriter();
- try {
- String actualStr = jsonObject.write(stringWriter,0,0).toString();
-
- assertEquals("length", str0.length(), actualStr.length());
- assertTrue("key1", actualStr.contains("\"key1\":\"value1\""));
- assertTrue("key2", actualStr.contains("\"key2\":[1,false,3.14]"));
- } finally {
- try {
- stringWriter.close();
- } catch (Exception e) {}
- }
-
- stringWriter = new StringWriter();
- try {
- String actualStr = jsonObject.write(stringWriter,2,1).toString();
-
- assertEquals("length", str2.length(), actualStr.length());
- assertTrue("key1", actualStr.contains(" \"key1\": \"value1\""));
- assertTrue("key2", actualStr.contains(" \"key2\": [\n" +
- " 1,\n" +
- " false,\n" +
- " 3.14\n" +
- " ]")
- );
- } finally {
- try {
- stringWriter.close();
- } catch (Exception e) {}
- }
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Exercise the JSONObject write(Appendable, int, int) method
- */
-/*
- @Test
- public void write3ParamAppendable() {
- String str0 = "{\"key1\":\"value1\",\"key2\":[1,false,3.14]}";
- String str2 =
- "{\n" +
- " \"key1\": \"value1\",\n" +
- " \"key2\": [\n" +
- " 1,\n" +
- " false,\n" +
- " 3.14\n" +
- " ]\n" +
- " }";
- JSONObject jsonObject = new JSONObject(str0);
- String expectedStr = str0;
- StringBuilder stringBuilder = new StringBuilder();
- Appendable appendable = jsonObject.write(stringBuilder,0,0);
- String actualStr = appendable.toString();
- assertEquals(expectedStr, actualStr);
-
- expectedStr = str2;
- stringBuilder = new StringBuilder();
- appendable = jsonObject.write(stringBuilder,2,1);
- actualStr = appendable.toString();
- assertEquals(expectedStr, actualStr);
- }
-*/
-
- /**
- * Exercise the JSONObject equals() method
- */
- @Test
- public void equals() {
- String str = "{\"key\":\"value\"}";
- JSONObject aJsonObject = new JSONObject(str);
- assertTrue("Same JSONObject should be equal to itself",
- aJsonObject.equals(aJsonObject));
- Util.checkJSONObjectMaps(aJsonObject);
- }
-
- /**
- * JSON null is not the same as Java null. This test examines the differences
- * in how they are handled by JSON-java.
- */
- @Test
- public void jsonObjectNullOperations() {
- /**
- * The Javadoc for JSONObject.NULL states:
- * "JSONObject.NULL is equivalent to the value that JavaScript calls null,
- * whilst Java's null is equivalent to the value that JavaScript calls
- * undefined."
- *
- * Standard ECMA-262 6th Edition / June 2015 (included to help explain the javadoc):
- * undefined value: primitive value used when a variable has not been assigned a value
- * Undefined type: type whose sole value is the undefined value
- * null value: primitive value that represents the intentional absence of any object value
- * Null type: type whose sole value is the null value
- * Java SE8 language spec (included to help explain the javadoc):
- * The Kinds of Types and Values ...
- * There is also a special null type, the type of the expression null, which has no name.
- * Because the null type has no name, it is impossible to declare a variable of the null
- * type or to cast to the null type. The null reference is the only possible value of an
- * expression of null type. The null reference can always be assigned or cast to any reference type.
- * In practice, the programmer can ignore the null type and just pretend that null is merely
- * a special literal that can be of any reference type.
- * Extensible Markup Language (XML) 1.0 Fifth Edition / 26 November 2008
- * No mention of null
- * ECMA-404 1st Edition / October 2013:
- * JSON Text ...
- * These are three literal name tokens: ...
- * null
- *
- * There seems to be no best practice to follow, it's all about what we
- * want the code to do.
- */
-
- // add JSONObject.NULL then convert to string in the manner of XML.toString()
- JSONObject jsonObjectJONull = new JSONObject();
- Object obj = JSONObject.NULL;
- jsonObjectJONull.put("key", obj);
- Object value = jsonObjectJONull.opt("key");
- assertTrue("opt() JSONObject.NULL should find JSONObject.NULL",
- obj.equals(value));
- value = jsonObjectJONull.get("key");
- assertTrue("get() JSONObject.NULL should find JSONObject.NULL",
- obj.equals(value));
- if (value == null) {
- value = "";
- }
- String string = value instanceof String ? (String)value : null;
- assertTrue("XML toString() should convert JSONObject.NULL to null",
- string == null);
-
- // now try it with null
- JSONObject jsonObjectNull = new JSONObject();
- obj = null;
- jsonObjectNull.put("key", obj);
- value = jsonObjectNull.opt("key");
- assertNull("opt() null should find null", value);
- // what is this trying to do? It appears to test absolutely nothing...
-// if (value == null) {
-// value = "";
-// }
-// string = value instanceof String ? (String)value : null;
-// assertTrue("should convert null to empty string", "".equals(string));
- try {
- value = jsonObjectNull.get("key");
- fail("get() null should throw exception");
- } catch (Exception ignored) {}
-
- /**
- * XML.toString() then goes on to do something with the value
- * if the key val is "content", then value.toString() will be
- * called. This will evaluate to "null" for JSONObject.NULL,
- * and the empty string for null.
- * But if the key is anything else, then JSONObject.NULL will be emitted
- * as null and null will be emitted as ""
- */
- String sJONull = XML.toString(jsonObjectJONull);
- assertTrue("JSONObject.NULL should emit a null value",
- "null ".equals(sJONull));
- String sNull = XML.toString(jsonObjectNull);
- assertTrue("null should emit an empty string", "".equals(sNull));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jsonObjectJONull, jsonObjectNull
- )));
- }
-
- @Test(expected = JSONPointerException.class)
- public void queryWithNoResult() {
- new JSONObject().query("/a/b");
- }
-
- @Test
- public void optQueryWithNoResult() {
- assertNull(new JSONObject().optQuery("/a/b"));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void optQueryWithSyntaxError() {
- new JSONObject().optQuery("invalid");
- }
-
- @Test(expected = JSONException.class)
- public void invalidEscapeSequence() {
- String json = "{ \"\\url\": \"value\" }";
- assertNull("Expected an exception",new JSONObject(json));
- }
-
- /**
- * Exercise JSONObject toMap() method.
- */
- @Test
- public void toMap() {
- String jsonObjectStr =
- "{" +
- "\"key1\":" +
- "[1,2," +
- "{\"key3\":true}" +
- "]," +
- "\"key2\":" +
- "{\"key1\":\"val1\",\"key2\":" +
- "{\"key2\":null}," +
- "\"key3\":42" +
- "}," +
- "\"key3\":" +
- "[" +
- "[\"value1\",2.1]" +
- "," +
- "[null]" +
- "]" +
- "}";
-
- JSONObject jsonObject = new JSONObject(jsonObjectStr);
- Map,?> map = jsonObject.toMap();
-
- assertTrue("Map should not be null", map != null);
- assertTrue("Map should have 3 elements", map.size() == 3);
-
- List> key1List = (List>)map.get("key1");
- assertTrue("key1 should not be null", key1List != null);
- assertTrue("key1 list should have 3 elements", key1List.size() == 3);
- assertTrue("key1 value 1 should be 1", key1List.get(0).equals(Integer.valueOf(1)));
- assertTrue("key1 value 2 should be 2", key1List.get(1).equals(Integer.valueOf(2)));
-
- Map,?> key1Value3Map = (Map,?>)key1List.get(2);
- assertTrue("Map should not be null", key1Value3Map != null);
- assertTrue("Map should have 1 element", key1Value3Map.size() == 1);
- assertTrue("Map key3 should be true", key1Value3Map.get("key3").equals(Boolean.TRUE));
-
- Map,?> key2Map = (Map,?>)map.get("key2");
- assertTrue("key2 should not be null", key2Map != null);
- assertTrue("key2 map should have 3 elements", key2Map.size() == 3);
- assertTrue("key2 map key 1 should be val1", key2Map.get("key1").equals("val1"));
- assertTrue("key2 map key 3 should be 42", key2Map.get("key3").equals(Integer.valueOf(42)));
-
- Map,?> key2Val2Map = (Map,?>)key2Map.get("key2");
- assertTrue("key2 map key 2 should not be null", key2Val2Map != null);
- assertTrue("key2 map key 2 should have an entry", key2Val2Map.containsKey("key2"));
- assertTrue("key2 map key 2 value should be null", key2Val2Map.get("key2") == null);
-
- List> key3List = (List>)map.get("key3");
- assertTrue("key3 should not be null", key3List != null);
- assertTrue("key3 list should have 3 elements", key3List.size() == 2);
-
- List> key3Val1List = (List>)key3List.get(0);
- assertTrue("key3 list val 1 should not be null", key3Val1List != null);
- assertTrue("key3 list val 1 should have 2 elements", key3Val1List.size() == 2);
- assertTrue("key3 list val 1 list element 1 should be value1", key3Val1List.get(0).equals("value1"));
- assertTrue("key3 list val 1 list element 2 should be 2.1", key3Val1List.get(1).equals(new BigDecimal("2.1")));
-
- List> key3Val2List = (List>)key3List.get(1);
- assertTrue("key3 list val 2 should not be null", key3Val2List != null);
- assertTrue("key3 list val 2 should have 1 element", key3Val2List.size() == 1);
- assertTrue("key3 list val 2 list element 1 should be null", key3Val2List.get(0) == null);
-
- // Assert that toMap() is a deep copy
- jsonObject.getJSONArray("key3").getJSONArray(0).put(0, "still value 1");
- assertTrue("key3 list val 1 list element 1 should be value1", key3Val1List.get(0).equals("value1"));
-
- // assert that the new map is mutable
- assertTrue("Removing a key should succeed", map.remove("key3") != null);
- assertTrue("Map should have 2 elements", map.size() == 2);
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * test that validates a singleton can be serialized as a bean.
- */
- @SuppressWarnings("boxing")
- @Test
- public void testSingletonBean() {
- final JSONObject jo = new JSONObject(Singleton.getInstance());
- assertEquals(jo.keySet().toString(), 1, jo.length());
- assertEquals(0, jo.get("someInt"));
- assertEquals(null, jo.opt("someString"));
-
- // Update the singleton values
- Singleton.getInstance().setSomeInt(42);
- Singleton.getInstance().setSomeString("Something");
- final JSONObject jo2 = new JSONObject(Singleton.getInstance());
- assertEquals(2, jo2.length());
- assertEquals(42, jo2.get("someInt"));
- assertEquals("Something", jo2.get("someString"));
-
- // ensure our original jo hasn't changed.
- assertEquals(0, jo.get("someInt"));
- assertEquals(null, jo.opt("someString"));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jo, jo2
- )));
- }
-
- /**
- * test that validates a singleton can be serialized as a bean.
- */
- @SuppressWarnings("boxing")
- @Test
- public void testSingletonEnumBean() {
- final JSONObject jo = new JSONObject(SingletonEnum.getInstance());
- assertEquals(jo.keySet().toString(), 1, jo.length());
- assertEquals(0, jo.get("someInt"));
- assertEquals(null, jo.opt("someString"));
-
- // Update the singleton values
- SingletonEnum.getInstance().setSomeInt(42);
- SingletonEnum.getInstance().setSomeString("Something");
- final JSONObject jo2 = new JSONObject(SingletonEnum.getInstance());
- assertEquals(2, jo2.length());
- assertEquals(42, jo2.get("someInt"));
- assertEquals("Something", jo2.get("someString"));
-
- // ensure our original jo hasn't changed.
- assertEquals(0, jo.get("someInt"));
- assertEquals(null, jo.opt("someString"));
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- jo, jo2
- )));
- }
-
- /**
- * Test to validate that a generic class can be serialized as a bean.
- */
- @SuppressWarnings("boxing")
- @Test
- public void testGenericBean() {
- GenericBean bean = new GenericBean<>(42);
- final JSONObject jo = new JSONObject(bean);
- assertEquals(jo.keySet().toString(), 8, jo.length());
- assertEquals(42, jo.get("genericValue"));
- assertEquals("Expected the getter to only be called once",
- 1, bean.genericGetCounter);
- assertEquals(0, bean.genericSetCounter);
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Test to validate that a generic class can be serialized as a bean.
- */
- @SuppressWarnings("boxing")
- @Test
- public void testGenericIntBean() {
- GenericBeanInt bean = new GenericBeanInt(42);
- final JSONObject jo = new JSONObject(bean);
- assertEquals(jo.keySet().toString(), 10, jo.length());
- assertEquals(42, jo.get("genericValue"));
- assertEquals("Expected the getter to only be called once",
- 1, bean.genericGetCounter);
- assertEquals(0, bean.genericSetCounter);
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Test to verify key limitations in the JSONObject bean serializer.
- */
- @Test
- public void testWierdListBean() {
- @SuppressWarnings("boxing")
- WeirdList bean = new WeirdList(42, 43, 44);
- final JSONObject jo = new JSONObject(bean);
- // get() should have a key of 0 length
- // get(int) should be ignored base on parameter count
- // getInt(int) should also be ignored based on parameter count
- // add(Integer) should be ignore as it doesn't start with get/is and also has a parameter
- // getALL should be mapped
- assertEquals("Expected 1 key to be mapped. Instead found: "+jo.keySet().toString(),
- 1, jo.length());
- assertNotNull(jo.get("ALL"));
- Util.checkJSONObjectMaps(jo);
- }
-
- /**
- * Sample test case from https://github.com/stleary/JSON-java/issues/531
- * which verifies that no regression in double/BigDecimal support is present.
- */
- @Test
- public void testObjectToBigDecimal() {
- double value = 1412078745.01074;
- Reader reader = new StringReader("[{\"value\": " + value + "}]");
- JSONTokener tokener = new JSONTokener(reader);
- JSONArray array = new JSONArray(tokener);
- JSONObject jsonObject = array.getJSONObject(0);
-
- BigDecimal current = jsonObject.getBigDecimal("value");
- BigDecimal wantedValue = BigDecimal.valueOf(value);
-
- assertEquals(current, wantedValue);
- Util.checkJSONObjectMaps(jsonObject);
- Util.checkJSONArrayMaps(array, jsonObject.getMapType());
- }
-
- /**
- * Tests the exception portions of populateMap.
- */
- @Test
- public void testExceptionalBean() {
- ExceptionalBean bean = new ExceptionalBean();
- final JSONObject jo = new JSONObject(bean);
- assertEquals("Expected 1 key to be mapped. Instead found: "+jo.keySet().toString(),
- 1, jo.length());
- assertTrue(jo.get("closeable") instanceof JSONObject);
- assertTrue(jo.getJSONObject("closeable").has("string"));
- Util.checkJSONObjectMaps(jo);
- }
-
- @Test(expected=NullPointerException.class)
- public void testPutNullBoolean() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, false);
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullCollection() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, Collections.emptySet());
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullDouble() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, 0.0d);
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullFloat() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, 0.0f);
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullInt() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, 0);
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullLong() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, 0L);
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullMap() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, Collections.emptyMap());
- fail("Expected an exception");
- }
- @Test(expected=NullPointerException.class)
- public void testPutNullObject() {
- // null put key
- JSONObject jsonObject = new JSONObject("{}");
- jsonObject.put(null, new Object());
- fail("Expected an exception");
- }
- @Test(expected=JSONException.class)
- public void testSelfRecursiveObject() {
- // A -> A ...
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- ObjA.setRef(ObjA);
- new JSONObject(ObjA);
- fail("Expected an exception");
- }
- @Test(expected=JSONException.class)
- public void testLongSelfRecursiveObject() {
- // B -> A -> A ...
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- ObjB.setRef(ObjA);
- ObjA.setRef(ObjA);
- new JSONObject(ObjB);
- fail("Expected an exception");
- }
- @Test(expected=JSONException.class)
- public void testSimpleRecursiveObject() {
- // B -> A -> B ...
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- ObjB.setRef(ObjA);
- ObjA.setRef(ObjB);
- new JSONObject(ObjA);
- fail("Expected an exception");
- }
- @Test(expected=JSONException.class)
- public void testLongRecursiveObject() {
- // D -> C -> B -> A -> D ...
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- RecursiveBean ObjC = new RecursiveBean("ObjC");
- RecursiveBean ObjD = new RecursiveBean("ObjD");
- ObjC.setRef(ObjB);
- ObjB.setRef(ObjA);
- ObjD.setRef(ObjC);
- ObjA.setRef(ObjD);
- new JSONObject(ObjB);
- fail("Expected an exception");
- }
- @Test(expected=JSONException.class)
- public void testRepeatObjectRecursive() {
- // C -> B -> A -> D -> C ...
- // -> D -> C ...
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- RecursiveBean ObjC = new RecursiveBean("ObjC");
- RecursiveBean ObjD = new RecursiveBean("ObjD");
- ObjC.setRef(ObjB);
- ObjB.setRef(ObjA);
- ObjB.setRef2(ObjD);
- ObjA.setRef(ObjD);
- ObjD.setRef(ObjC);
- new JSONObject(ObjC);
- fail("Expected an exception");
- }
- @Test
- public void testRepeatObjectNotRecursive() {
- // C -> B -> A
- // -> A
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- RecursiveBean ObjC = new RecursiveBean("ObjC");
- ObjC.setRef(ObjA);
- ObjB.setRef(ObjA);
- ObjB.setRef2(ObjA);
- JSONObject j0 = new JSONObject(ObjC);
- JSONObject j1 = new JSONObject(ObjB);
- JSONObject j2 = new JSONObject(ObjA);
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- j0, j1, j2
- )));
- }
- @Test
- public void testLongRepeatObjectNotRecursive() {
- // C -> B -> A -> D -> E
- // -> D -> E
- RecursiveBean ObjA = new RecursiveBean("ObjA");
- RecursiveBean ObjB = new RecursiveBean("ObjB");
- RecursiveBean ObjC = new RecursiveBean("ObjC");
- RecursiveBean ObjD = new RecursiveBean("ObjD");
- RecursiveBean ObjE = new RecursiveBean("ObjE");
- ObjC.setRef(ObjB);
- ObjB.setRef(ObjA);
- ObjB.setRef2(ObjD);
- ObjA.setRef(ObjD);
- ObjD.setRef(ObjE);
- JSONObject j0 = new JSONObject(ObjC);
- JSONObject j1 = new JSONObject(ObjB);
- JSONObject j2 = new JSONObject(ObjA);
- JSONObject j3 = new JSONObject(ObjD);
- JSONObject j4 = new JSONObject(ObjE);
- Util.checkJSONObjectsMaps(new ArrayList(Arrays.asList(
- j0, j1, j2, j3, j4
- )));
- }
- @Test(expected=JSONException.class)
- public void testRecursiveEquals() {
- RecursiveBeanEquals a = new RecursiveBeanEquals("same");
- a.setRef(a);
- JSONObject j0 = new JSONObject(a);
- Util.checkJSONObjectMaps(j0);
- }
- @Test
- public void testNotRecursiveEquals() {
- RecursiveBeanEquals a = new RecursiveBeanEquals("same");
- RecursiveBeanEquals b = new RecursiveBeanEquals("same");
- RecursiveBeanEquals c = new RecursiveBeanEquals("same");
- a.setRef(b);
- b.setRef(c);
- JSONObject j0 = new JSONObject(a);
- Util.checkJSONObjectMaps(j0);
- }
-
-
- @Test
- public void testIssue548ObjectWithEmptyJsonArray() {
- JSONObject jsonObject = new JSONObject("{\"empty_json_array\": []}");
- assertTrue("missing expected key 'empty_json_array'", jsonObject.has("empty_json_array"));
- assertNotNull("'empty_json_array' should be an array", jsonObject.getJSONArray("empty_json_array"));
- assertEquals("'empty_json_array' should have a length of 0", 0, jsonObject.getJSONArray("empty_json_array").length());
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Tests if calling JSONObject clear() method actually makes the JSONObject empty
- */
- @Test(expected = JSONException.class)
- public void jsonObjectClearMethodTest() {
- //Adds random stuff to the JSONObject
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("key1", 123);
- jsonObject.put("key2", "456");
- jsonObject.put("key3", new JSONObject());
- jsonObject.clear(); //Clears the JSONObject
- assertTrue("expected jsonObject.length() == 0", jsonObject.length() == 0); //Check if its length is 0
- jsonObject.getInt("key1"); //Should throws org.json.JSONException: JSONObject["asd"] not found
- Util.checkJSONObjectMaps(jsonObject);
- }
-
- /**
- * Tests for stack overflow. See https://github.com/stleary/JSON-java/issues/654
- */
- @Test(expected = JSONException.class)
- public void issue654StackOverflowInput() {
- //String base64Bytes ="eyJHWiI6Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMCkwLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7CXt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMCkwLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7CXt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3sJe3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTApMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3sJe3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTApMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMCkwLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7CXt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMCkwLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7CXt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3sJe3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTApMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3sJe3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTApMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7ewl7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7c3t7e3t7e3vPAAAAAAAAAHt7e3t7e3t7e3t7e3t7e3t7e3t7e1ste3t7e3t7e3t7e3t7e3t7e3t7e3t7CXt7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3tbLTAtMCx7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e1stMC0wLHt7e3t7e3t7e3t7e3t7e3t7e88AAAAAAAAAe3t7e3t7e3t7e3t7e3t7e3t7e3t7Wy0wLTAse3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7e3t7f3syMv//e3t7e3t7e3t7e3t7e3sx//////8=";
- //String input = new String(java.util.Base64.getDecoder().decode(base64Bytes));
- String input = "{\"GZ\":[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0)0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{{{{{{{{{{{{{{{{{{{{[-0-0,{{{{{{{{{{s{{{{{{{";
- JSONObject json_input = new JSONObject(input);
- assertNotNull(json_input);
- fail("Excepected Exception.");
- Util.checkJSONObjectMaps(json_input);
- }
-
- /**
- * Tests for incorrect object/array nesting. See https://github.com/stleary/JSON-java/issues/654
- */
- @Test(expected = JSONException.class)
- public void issue654IncorrectNestingNoKey1() {
- JSONObject json_input = new JSONObject("{{\"a\":0}}");
- assertNotNull(json_input);
- fail("Expected Exception.");
- }
-
- /**
- * Tests for incorrect object/array nesting. See https://github.com/stleary/JSON-java/issues/654
- */
- @Test(expected = JSONException.class)
- public void issue654IncorrectNestingNoKey2() {
- JSONObject json_input = new JSONObject("{[\"a\"]}");
- assertNotNull(json_input);
- fail("Excepected Exception.");
- }
-
- /**
- * Tests for stack overflow. See https://github.com/stleary/JSON-java/issues/654
- */
- @Ignore("This test relies on system constraints and may not always pass. See: https://github.com/stleary/JSON-java/issues/821")
- @Test(expected = JSONException.class)
- public void issue654StackOverflowInputWellFormed() {
- //String input = new String(java.util.Base64.getDecoder().decode(base64Bytes));
- final InputStream resourceAsStream = JSONObjectTest.class.getClassLoader().getResourceAsStream("Issue654WellFormedObject.json");
- JSONTokener tokener = new JSONTokener(resourceAsStream);
- JSONObject json_input = new JSONObject(tokener);
- assertNotNull(json_input);
- fail("Excepected Exception due to stack overflow.");
- }
-
- @Test
- public void testIssue682SimilarityOfJSONString() {
- JSONObject jo1 = new JSONObject()
- .put("a", new MyJsonString())
- .put("b", 2);
- JSONObject jo2 = new JSONObject()
- .put("a", new MyJsonString())
- .put("b", 2);
- assertTrue(jo1.similar(jo2));
-
- JSONObject jo3 = new JSONObject()
- .put("a", new JSONString() {
- @Override
- public String toJSONString() {
- return "\"different value\"";
- }
- })
- .put("b", 2);
- assertFalse(jo1.similar(jo3));
- }
-
- private static final Number[] NON_FINITE_NUMBERS = { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN,
- Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.NaN };
-
- @Test
- public void issue713MapConstructorWithNonFiniteNumbers() {
- for (Number nonFinite : NON_FINITE_NUMBERS) {
- Map map = new HashMap<>();
- map.put("a", nonFinite);
-
- assertThrows(JSONException.class, () -> new JSONObject(map));
- }
- }
-
- @Test
- public void issue713BeanConstructorWithNonFiniteNumbers() {
- for (Number nonFinite : NON_FINITE_NUMBERS) {
- GenericBean bean = new GenericBean<>(nonFinite);
- assertThrows(JSONException.class, () -> new JSONObject(bean));
- }
- }
-
- @Test(expected = JSONException.class)
- public void issue743SerializationMap() {
- HashMap map = new HashMap<>();
- map.put("t", map);
- JSONObject object = new JSONObject(map);
- String jsonString = object.toString();
- }
-
- @Test(expected = JSONException.class)
- public void testCircularReferenceMultipleLevel() {
- HashMap inside = new HashMap<>();
- HashMap jsonObject = new HashMap<>();
- inside.put("inside", jsonObject);
- jsonObject.put("test", inside);
- new JSONObject(jsonObject);
- }
-
- @Test
- public void issue743SerializationMapWith512Objects() {
- HashMap map = buildNestedMap(ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
- JSONObject object = new JSONObject(map);
- String jsonString = object.toString();
- }
-
- @Test
- public void issue743SerializationMapWith1000Objects() {
- HashMap map = buildNestedMap(1000);
- JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withMaxNestingDepth(1000);
- JSONObject object = new JSONObject(map, parserConfiguration);
- String jsonString = object.toString();
- }
-
- @Test(expected = JSONException.class)
- public void issue743SerializationMapWith1001Objects() {
- HashMap map = buildNestedMap(1001);
- JSONObject object = new JSONObject(map);
- String jsonString = object.toString();
- }
-
- @Test(expected = JSONException.class)
- public void testCircleReferenceFirstLevel() {
- Map jsonObject = new HashMap<>();
-
- jsonObject.put("test", jsonObject);
-
- new JSONObject(jsonObject, new JSONParserConfiguration());
- }
-
- @Test(expected = StackOverflowError.class)
- public void testCircleReferenceMultiplyLevel_notConfigured_expectedStackOverflow() {
- Map inside = new HashMap<>();
-
- Map