mirror of
https://github.com/fankes/JSON-java-compat.git
synced 2025-09-08 03:24:27 +08:00
Merge branch 'master' into 863-improve-toString-performance-StringBuilderWriter
This commit is contained in:
@@ -14,22 +14,10 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.json.NumberConversionUtil.potentialNumber;
|
||||
import static org.json.NumberConversionUtil.stringToNumber;
|
||||
|
||||
/**
|
||||
* A JSONObject is an unordered collection of name/value pairs. Its external
|
||||
* form is a string wrapped in curly braces with colons between the names and
|
||||
@@ -207,6 +195,21 @@ public class JSONObject {
|
||||
* duplicated key.
|
||||
*/
|
||||
public JSONObject(JSONTokener x) throws JSONException {
|
||||
this(x, new JSONParserConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a JSONTokener with custom json parse configurations.
|
||||
*
|
||||
* @param x
|
||||
* A JSONTokener object containing the source string.
|
||||
* @param jsonParserConfiguration
|
||||
* Variable to pass parser custom configuration for json parsing.
|
||||
* @throws JSONException
|
||||
* If there is a syntax error in the source string or a
|
||||
* duplicated key.
|
||||
*/
|
||||
public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
|
||||
this();
|
||||
char c;
|
||||
String key;
|
||||
@@ -236,13 +239,14 @@ public class JSONObject {
|
||||
|
||||
if (key != null) {
|
||||
// Check if key exists
|
||||
if (this.opt(key) != null) {
|
||||
// key already exists
|
||||
boolean keyExists = this.opt(key) != null;
|
||||
if (keyExists && !jsonParserConfiguration.isOverwriteDuplicateKey()) {
|
||||
throw x.syntaxError("Duplicate key \"" + key + "\"");
|
||||
}
|
||||
// Only add value if non-null
|
||||
|
||||
Object value = x.nextValue();
|
||||
if (value!=null) {
|
||||
// Only add value if non-null
|
||||
if (value != null) {
|
||||
this.put(key, value);
|
||||
}
|
||||
}
|
||||
@@ -298,7 +302,6 @@ public class JSONObject {
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a map with recursion depth.
|
||||
*
|
||||
*/
|
||||
private JSONObject(Map<?, ?> m, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
|
||||
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
|
||||
@@ -429,7 +432,25 @@ public class JSONObject {
|
||||
* duplicated key.
|
||||
*/
|
||||
public JSONObject(String source) throws JSONException {
|
||||
this(new JSONTokener(source));
|
||||
this(source, new JSONParserConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a JSONObject from a source JSON text string with custom json parse configurations.
|
||||
* This is the most commonly used JSONObject constructor.
|
||||
*
|
||||
* @param source
|
||||
* A string beginning with <code>{</code> <small>(left
|
||||
* brace)</small> and ending with <code>}</code>
|
||||
* <small>(right brace)</small>.
|
||||
* @param jsonParserConfiguration
|
||||
* Variable to pass parser custom configuration for json parsing.
|
||||
* @exception JSONException
|
||||
* If there is a syntax error in the source string or a
|
||||
* duplicated key.
|
||||
*/
|
||||
public JSONObject(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
|
||||
this(new JSONTokener(source), jsonParserConfiguration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2462,7 +2483,8 @@ public class JSONObject {
|
||||
* produced, then the value will just be a string.
|
||||
*/
|
||||
|
||||
if (potentialNumber(string)) {
|
||||
char initial = string.charAt(0);
|
||||
if ((initial >= '0' && initial <= '9') || initial == '-') {
|
||||
try {
|
||||
return stringToNumber(string);
|
||||
} catch (Exception ignore) {
|
||||
@@ -2471,8 +2493,75 @@ public class JSONObject {
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to a number using the narrowest possible type. Possible
|
||||
* returns for this function are BigDecimal, Double, BigInteger, Long, and Integer.
|
||||
* When a Double is returned, it should always be a valid Double and not NaN or +-infinity.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
protected static Number stringToNumber(final String val) throws NumberFormatException {
|
||||
char initial = val.charAt(0);
|
||||
if ((initial >= '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.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the object is a NaN or infinite number.
|
||||
@@ -2906,5 +2995,23 @@ public class JSONObject {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For a prospective number, remove the leading zeros
|
||||
* @param value prospective number
|
||||
* @return number without leading zeros
|
||||
*/
|
||||
private static String removeLeadingZerosOfNumber(String value){
|
||||
if (value.equals("-")){return value;}
|
||||
boolean negativeFirstChar = (value.charAt(0) == '-');
|
||||
int counter = negativeFirstChar ? 1:0;
|
||||
while (counter < value.length()){
|
||||
if (value.charAt(counter) != '0'){
|
||||
if (negativeFirstChar) {return "-".concat(value.substring(counter));}
|
||||
return value.substring(counter);
|
||||
}
|
||||
++counter;
|
||||
}
|
||||
if (negativeFirstChar) {return "-0";}
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user