mirror of
https://github.com/fankes/JSON-java-compat.git
synced 2025-09-09 12:04:28 +08:00
Merge branch 'stleary:master' into feature-disable-whitespace-trim
This commit is contained in:
@@ -46,19 +46,19 @@ public class CookieList {
|
||||
* @throws JSONException if a called function fails
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
boolean b = false;
|
||||
boolean isEndOfPair = false;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
// Don't use the new entrySet API to maintain Android support
|
||||
for (final String key : jo.keySet()) {
|
||||
final Object value = jo.opt(key);
|
||||
if (!JSONObject.NULL.equals(value)) {
|
||||
if (b) {
|
||||
if (isEndOfPair) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(Cookie.escape(key));
|
||||
sb.append("=");
|
||||
sb.append(Cookie.escape(value.toString()));
|
||||
b = true;
|
||||
isEndOfPair = true;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
@@ -149,11 +149,40 @@ public class JSONArray implements Iterable<Object> {
|
||||
* A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<?> collection) {
|
||||
this(collection, 0, new JSONParserConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a Collection.
|
||||
*
|
||||
* @param collection
|
||||
* A Collection.
|
||||
* @param jsonParserConfiguration
|
||||
* Configuration object for the JSON parser
|
||||
*/
|
||||
public JSONArray(Collection<?> collection, JSONParserConfiguration jsonParserConfiguration) {
|
||||
this(collection, 0, jsonParserConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONArray from a collection with recursion depth.
|
||||
*
|
||||
* @param collection
|
||||
* A Collection.
|
||||
* @param recursionDepth
|
||||
* Variable for tracking the count of nested object creations.
|
||||
* @param jsonParserConfiguration
|
||||
* Configuration object for the JSON parser
|
||||
*/
|
||||
JSONArray(Collection<?> collection, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
|
||||
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
|
||||
throw new JSONException("JSONArray has reached recursion depth limit of " + jsonParserConfiguration.getMaxNestingDepth());
|
||||
}
|
||||
if (collection == null) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
} else {
|
||||
this.myArrayList = new ArrayList<Object>(collection.size());
|
||||
this.addAll(collection, true);
|
||||
this.addAll(collection, true, recursionDepth, jsonParserConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +234,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
throw new JSONException(
|
||||
"JSONArray initial value should be a string or collection or array.");
|
||||
}
|
||||
this.addAll(array, true);
|
||||
this.addAll(array, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1330,7 +1359,8 @@ public class JSONArray implements Iterable<Object> {
|
||||
* The subscript.
|
||||
* @param value
|
||||
* The Map value.
|
||||
* @return this.
|
||||
* @return
|
||||
* reference to self
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is an invalid
|
||||
* number.
|
||||
@@ -1338,7 +1368,27 @@ public class JSONArray implements Iterable<Object> {
|
||||
* If a key in the map is <code>null</code>
|
||||
*/
|
||||
public JSONArray put(int index, Map<?, ?> value) throws JSONException {
|
||||
this.put(index, new JSONObject(value));
|
||||
this.put(index, new JSONObject(value, new JSONParserConfiguration()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the JSONArray, where the value will be a JSONObject that
|
||||
* is produced from a Map.
|
||||
*
|
||||
* @param index
|
||||
* The subscript
|
||||
* @param value
|
||||
* The Map value.
|
||||
* @param jsonParserConfiguration
|
||||
* Configuration object for the JSON parser
|
||||
* @return reference to self
|
||||
* @throws JSONException
|
||||
* If the index is negative or if the value is an invalid
|
||||
* number.
|
||||
*/
|
||||
public JSONArray put(int index, Map<?, ?> value, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
|
||||
this.put(index, new JSONObject(value, jsonParserConfiguration));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1779,13 +1829,14 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
*
|
||||
* @param recursionDepth
|
||||
* Variable for tracking the count of nested object creations.
|
||||
*/
|
||||
private void addAll(Collection<?> collection, boolean wrap) {
|
||||
private void addAll(Collection<?> collection, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
|
||||
this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size());
|
||||
if (wrap) {
|
||||
for (Object o: collection){
|
||||
this.put(JSONObject.wrap(o));
|
||||
this.put(JSONObject.wrap(o, recursionDepth + 1, jsonParserConfiguration));
|
||||
}
|
||||
} else {
|
||||
for (Object o: collection){
|
||||
@@ -1814,7 +1865,24 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an array's elements to the JSONArray.
|
||||
*
|
||||
* @param array
|
||||
* Array. If the parameter passed is null, or not an array,
|
||||
* JSONArray, Collection, or Iterable, an exception will be
|
||||
* thrown.
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
* @throws JSONException
|
||||
* If not an array or if an array value is non-finite number.
|
||||
*/
|
||||
private void addAll(Object array, boolean wrap) throws JSONException {
|
||||
this.addAll(array, wrap, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an array's elements to the JSONArray.
|
||||
*
|
||||
@@ -1823,21 +1891,40 @@ public class JSONArray implements Iterable<Object> {
|
||||
* JSONArray, Collection, or Iterable, an exception will be
|
||||
* thrown.
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
* @param recursionDepth
|
||||
* Variable for tracking the count of nested object creations.
|
||||
*/
|
||||
private void addAll(Object array, boolean wrap, int recursionDepth) {
|
||||
addAll(array, wrap, recursionDepth, new JSONParserConfiguration());
|
||||
}
|
||||
/**
|
||||
* Add an array's elements to the JSONArray.
|
||||
*`
|
||||
* @param array
|
||||
* Array. If the parameter passed is null, or not an array,
|
||||
* JSONArray, Collection, or Iterable, an exception will be
|
||||
* thrown.
|
||||
* @param wrap
|
||||
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
|
||||
* {@code false} to add the items directly
|
||||
*
|
||||
* @param recursionDepth
|
||||
* Variable for tracking the count of nested object creations.
|
||||
* @param jsonParserConfiguration
|
||||
* Variable to pass parser custom configuration for json parsing.
|
||||
* @throws JSONException
|
||||
* If not an array or if an array value is non-finite number.
|
||||
* @throws NullPointerException
|
||||
* Thrown if the array parameter is null.
|
||||
*/
|
||||
private void addAll(Object array, boolean wrap) throws JSONException {
|
||||
private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
this.myArrayList.ensureCapacity(this.myArrayList.size() + length);
|
||||
if (wrap) {
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
this.put(JSONObject.wrap(Array.get(array, i), recursionDepth + 1, jsonParserConfiguration));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
@@ -1850,7 +1937,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
// JSONArray
|
||||
this.myArrayList.addAll(((JSONArray)array).myArrayList);
|
||||
} else if (array instanceof Collection) {
|
||||
this.addAll((Collection<?>)array, wrap);
|
||||
this.addAll((Collection<?>)array, wrap, recursionDepth);
|
||||
} else if (array instanceof Iterable) {
|
||||
this.addAll((Iterable<?>)array, wrap);
|
||||
} else {
|
||||
|
@@ -55,11 +55,13 @@ public class JSONMLParserConfiguration extends ParserConfiguration {
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
return super.withKeepStrings(newVal);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
|
||||
return super.withMaxNestingDepth(maxNestingDepth);
|
||||
|
@@ -276,6 +276,30 @@ public class JSONObject {
|
||||
* If a key in the map is <code>null</code>
|
||||
*/
|
||||
public JSONObject(Map<?, ?> m) {
|
||||
this(m, 0, new JSONParserConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a Map with custom json parse configurations.
|
||||
*
|
||||
* @param m
|
||||
* A map object that can be used to initialize the contents of
|
||||
* the JSONObject.
|
||||
* @param jsonParserConfiguration
|
||||
* Variable to pass parser custom configuration for json parsing.
|
||||
*/
|
||||
public JSONObject(Map<?, ?> m, JSONParserConfiguration jsonParserConfiguration) {
|
||||
this(m, 0, jsonParserConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a map with recursion depth.
|
||||
*
|
||||
*/
|
||||
private JSONObject(Map<?, ?> m, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
|
||||
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
|
||||
throw new JSONException("JSONObject has reached recursion depth limit of " + jsonParserConfiguration.getMaxNestingDepth());
|
||||
}
|
||||
if (m == null) {
|
||||
this.map = new HashMap<String, Object>();
|
||||
} else {
|
||||
@@ -287,7 +311,7 @@ public class JSONObject {
|
||||
final Object value = e.getValue();
|
||||
if (value != null) {
|
||||
testValidity(value);
|
||||
this.map.put(String.valueOf(e.getKey()), wrap(value));
|
||||
this.map.put(String.valueOf(e.getKey()), wrap(value, recursionDepth + 1, jsonParserConfiguration));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1841,6 +1865,10 @@ public class JSONObject {
|
||||
}
|
||||
}
|
||||
|
||||
//If the superclass is Object, no annotations will be found any more
|
||||
if (c.getSuperclass().equals(Object.class))
|
||||
return null;
|
||||
|
||||
try {
|
||||
return getAnnotation(
|
||||
c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
|
||||
@@ -1895,6 +1923,10 @@ public class JSONObject {
|
||||
}
|
||||
}
|
||||
|
||||
//If the superclass is Object, no annotations will be found any more
|
||||
if (c.getSuperclass().equals(Object.class))
|
||||
return -1;
|
||||
|
||||
try {
|
||||
int d = getAnnotationDepth(
|
||||
c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
|
||||
@@ -2566,7 +2598,31 @@ public class JSONObject {
|
||||
return wrap(object, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an object, if necessary. If the object is <code>null</code>, 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<Object> objectsRecord) {
|
||||
return wrap(object, objectsRecord, 0, new JSONParserConfiguration());
|
||||
}
|
||||
|
||||
private static Object wrap(Object object, Set<Object> objectsRecord, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
|
||||
try {
|
||||
if (NULL.equals(object)) {
|
||||
return NULL;
|
||||
@@ -2584,14 +2640,14 @@ public class JSONObject {
|
||||
|
||||
if (object instanceof Collection) {
|
||||
Collection<?> coll = (Collection<?>) object;
|
||||
return new JSONArray(coll);
|
||||
return new JSONArray(coll, recursionDepth, jsonParserConfiguration);
|
||||
}
|
||||
if (object.getClass().isArray()) {
|
||||
return new JSONArray(object);
|
||||
}
|
||||
if (object instanceof Map) {
|
||||
Map<?, ?> map = (Map<?, ?>) object;
|
||||
return new JSONObject(map);
|
||||
return new JSONObject(map, recursionDepth, jsonParserConfiguration);
|
||||
}
|
||||
Package objectPackage = object.getClass().getPackage();
|
||||
String objectPackageName = objectPackage != null ? objectPackage
|
||||
|
26
src/main/java/org/json/JSONParserConfiguration.java
Normal file
26
src/main/java/org/json/JSONParserConfiguration.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package org.json;
|
||||
|
||||
/**
|
||||
* Configuration object for the JSON parser. The configuration is immutable.
|
||||
*/
|
||||
public class JSONParserConfiguration extends ParserConfiguration {
|
||||
|
||||
/**
|
||||
* Configuration with the default values.
|
||||
*/
|
||||
public JSONParserConfiguration() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JSONParserConfiguration clone() {
|
||||
return new JSONParserConfiguration();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public JSONParserConfiguration withMaxNestingDepth(final int maxNestingDepth) {
|
||||
return super.withMaxNestingDepth(maxNestingDepth);
|
||||
}
|
||||
|
||||
}
|
@@ -24,7 +24,7 @@ class NumberConversionUtil {
|
||||
val = "-0."+val.substring(2);
|
||||
}
|
||||
char initial = val.charAt(0);
|
||||
if ((initial >= '0' && initial <= '9') || initial == '-' ) {
|
||||
if ( isNumericChar(initial) || initial == '-' ) {
|
||||
// decimal representation
|
||||
if (isDecimalNotation(val)) {
|
||||
// Use a BigDecimal all the time so we keep the original
|
||||
@@ -53,13 +53,13 @@ class NumberConversionUtil {
|
||||
initial = val.charAt(0);
|
||||
if(initial == '0' && val.length() > 1) {
|
||||
char at1 = val.charAt(1);
|
||||
if(at1 >= '0' && at1 <= '9') {
|
||||
if(isNumericChar(at1)) {
|
||||
throw new NumberFormatException("val ["+input+"] 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') {
|
||||
if(at1 == '0' && isNumericChar(at2)) {
|
||||
throw new NumberFormatException("val ["+input+"] is not a valid number.");
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,16 @@ class NumberConversionUtil {
|
||||
throw new NumberFormatException("val ["+input+"] is not a valid number.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the character is a numeric digit ('0' to '9').
|
||||
*
|
||||
* @param c The character to be checked.
|
||||
* @return true if the character is a numeric digit, false otherwise.
|
||||
*/
|
||||
private static boolean isNumericChar(char c) {
|
||||
return (c <= '9' && c >= '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value could be considered a number in decimal number system.
|
||||
* @param value
|
||||
|
@@ -75,6 +75,7 @@ public class ParserConfiguration {
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ParserConfiguration> T withKeepStrings(final boolean newVal) {
|
||||
T newConfig = (T)this.clone();
|
||||
newConfig.keepStrings = newVal;
|
||||
@@ -101,6 +102,7 @@ public class ParserConfiguration {
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends ParserConfiguration> T withMaxNestingDepth(int maxNestingDepth) {
|
||||
T newConfig = (T)this.clone();
|
||||
|
||||
|
@@ -892,14 +892,14 @@ public class XML {
|
||||
|
||||
|
||||
string = (object == null) ? "null" : escape(object.toString());
|
||||
|
||||
String indentationSuffix = (indentFactor > 0) ? "\n" : "";
|
||||
if(tagName == null){
|
||||
return indent(indent) + "\"" + string + "\"" + ((indentFactor > 0) ? "\n" : "");
|
||||
return indent(indent) + "\"" + string + "\"" + indentationSuffix;
|
||||
} else if(string.length() == 0){
|
||||
return indent(indent) + "<" + tagName + "/>" + ((indentFactor > 0) ? "\n" : "");
|
||||
return indent(indent) + "<" + tagName + "/>" + indentationSuffix;
|
||||
} else {
|
||||
return indent(indent) + "<" + tagName
|
||||
+ ">" + string + "</" + tagName + ">" + ((indentFactor > 0) ? "\n" : "");
|
||||
+ ">" + string + "</" + tagName + ">" + indentationSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -204,6 +204,7 @@ public class XMLParserConfiguration extends ParserConfiguration {
|
||||
*
|
||||
* @return The existing configuration will not be modified. A new configuration is returned.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public XMLParserConfiguration withKeepStrings(final boolean newVal) {
|
||||
return super.withKeepStrings(newVal);
|
||||
@@ -321,6 +322,7 @@ public class XMLParserConfiguration extends ParserConfiguration {
|
||||
* @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);
|
||||
@@ -328,7 +330,7 @@ public class XMLParserConfiguration extends ParserConfiguration {
|
||||
|
||||
/**
|
||||
* To enable explicit end tag with empty value.
|
||||
* @param closeEmptyTag
|
||||
* @param closeEmptyTag new value for the closeEmptyTag property
|
||||
* @return same instance of configuration with empty tag config updated
|
||||
*/
|
||||
public XMLParserConfiguration withCloseEmptyTag(boolean closeEmptyTag){
|
||||
|
Reference in New Issue
Block a user