mirror of
https://github.com/stleary/JSON-java.git
synced 2026-01-24 00:03:17 -05:00
Compare commits
86 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdf3cf7f81 | ||
|
|
2565abdaaa | ||
|
|
de855c50aa | ||
|
|
4cb1ae802a | ||
|
|
2e0a8137bd | ||
|
|
f177c97258 | ||
|
|
7d8353401a | ||
|
|
7fed023080 | ||
|
|
d9b8507e6a | ||
|
|
d345bc528e | ||
|
|
6f238a3698 | ||
|
|
4dbc5ef803 | ||
|
|
5c80c9157d | ||
|
|
a129ebe8e4 | ||
|
|
641b68dd55 | ||
|
|
643b25140f | ||
|
|
5024f2d210 | ||
|
|
16baa323cf | ||
|
|
52845366bd | ||
|
|
e7e6ed9205 | ||
|
|
1add1247fa | ||
|
|
5b2e5e7579 | ||
|
|
c9ae1f17d7 | ||
|
|
246350bbcd | ||
|
|
2fbe4d96cf | ||
|
|
3645f91b55 | ||
|
|
9c092753b0 | ||
|
|
d0f5607998 | ||
|
|
ad6bdd715d | ||
|
|
ef7a5e40be | ||
|
|
237bf0adb6 | ||
|
|
f76fbe7005 | ||
|
|
4f5bf16676 | ||
|
|
fbd2be7431 | ||
|
|
757b6edb03 | ||
|
|
f2b642a1ca | ||
|
|
04d6e83fc2 | ||
|
|
849b392c01 | ||
|
|
a7f8ff24df | ||
|
|
1ab5260a7a | ||
|
|
c28a2bdf39 | ||
|
|
382f62e781 | ||
|
|
0c7bd725a6 | ||
|
|
fcdb8671b2 | ||
|
|
c46774cf13 | ||
|
|
bd4b180f4e | ||
|
|
a8d4e4734f | ||
|
|
4865f51dd5 | ||
|
|
c870094f69 | ||
|
|
cbd8b18c4a | ||
|
|
f12fa9ba5f | ||
|
|
ae1e9e2b6a | ||
|
|
80e2ea2a80 | ||
|
|
2917104b53 | ||
|
|
9e0fc5e680 | ||
|
|
724fb888f7 | ||
|
|
eb806f4c14 | ||
|
|
5ff8b4cb08 | ||
|
|
5ef4f58ef1 | ||
|
|
413bb53b48 | ||
|
|
237376eca6 | ||
|
|
e0616a129e | ||
|
|
93ffca36c3 | ||
|
|
e477d7002b | ||
|
|
fb1db9341e | ||
|
|
adb0478f66 | ||
|
|
f58a0f4684 | ||
|
|
c11e09959c | ||
|
|
68f92eb395 | ||
|
|
34652a8706 | ||
|
|
a2d3b59394 | ||
|
|
c24be0e4ea | ||
|
|
88f65c5bea | ||
|
|
ebe69df8e4 | ||
|
|
2f2cd4dfc5 | ||
|
|
349a209df3 | ||
|
|
7851e9b2e8 | ||
|
|
7232a95c0b | ||
|
|
f96f505188 | ||
|
|
91107e3e82 | ||
|
|
4e8e24d49d | ||
|
|
f881b61c81 | ||
|
|
37582a44ad | ||
|
|
154cfda9aa | ||
|
|
45a7decba4 | ||
|
|
0c157cae75 |
7
CDL.java
7
CDL.java
@@ -70,9 +70,12 @@ public class CDL {
|
||||
c = x.next();
|
||||
if (c == q) {
|
||||
//Handle escaped double-quote
|
||||
if(x.next() != '\"')
|
||||
{
|
||||
char nextC = x.next();
|
||||
if(nextC != '\"') {
|
||||
// if our quote was the end of the file, don't step
|
||||
if(nextC > 0) {
|
||||
x.back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.json;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/*
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
@@ -24,8 +26,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Convert a web browser cookie list string to a JSONObject and back.
|
||||
* @author JSON.org
|
||||
@@ -39,7 +39,7 @@ public class CookieList {
|
||||
* The pairs are separated by ';'. The names and the values
|
||||
* will be unescaped, possibly converting '+' and '%' sequences.
|
||||
*
|
||||
* To add a cookie to a cooklist,
|
||||
* To add a cookie to a cookie list,
|
||||
* cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
||||
* cookieJSONObject.getString("value"));
|
||||
* @param string A cookie list string
|
||||
@@ -69,18 +69,17 @@ public class CookieList {
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
boolean b = false;
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!jo.isNull(string)) {
|
||||
for (final Entry<String,?> entry : jo.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (!JSONObject.NULL.equals(value)) {
|
||||
if (b) {
|
||||
sb.append(';');
|
||||
}
|
||||
sb.append(Cookie.escape(string));
|
||||
sb.append(Cookie.escape(key));
|
||||
sb.append("=");
|
||||
sb.append(Cookie.escape(jo.getString(string)));
|
||||
sb.append(Cookie.escape(value.toString()));
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
|
||||
21
HTTP.java
21
HTTP.java
@@ -24,7 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* Convert an HTTP header to a JSONObject and back.
|
||||
@@ -74,7 +75,7 @@ public class HTTP {
|
||||
String token;
|
||||
|
||||
token = x.nextToken();
|
||||
if (token.toUpperCase().startsWith("HTTP")) {
|
||||
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
|
||||
|
||||
// Response
|
||||
|
||||
@@ -125,8 +126,6 @@ public class HTTP {
|
||||
* information.
|
||||
*/
|
||||
public static String toString(JSONObject jo) throws JSONException {
|
||||
Iterator<String> keys = jo.keys();
|
||||
String string;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
||||
sb.append(jo.getString("HTTP-Version"));
|
||||
@@ -146,14 +145,14 @@ public class HTTP {
|
||||
throw new JSONException("Not enough material for an HTTP header.");
|
||||
}
|
||||
sb.append(CRLF);
|
||||
while (keys.hasNext()) {
|
||||
string = keys.next();
|
||||
if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) &&
|
||||
!"Reason-Phrase".equals(string) && !"Method".equals(string) &&
|
||||
!"Request-URI".equals(string) && !jo.isNull(string)) {
|
||||
sb.append(string);
|
||||
for (final Entry<String,?> entry : jo.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
|
||||
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
|
||||
!"Request-URI".equals(key) && !JSONObject.NULL.equals(entry.getValue())) {
|
||||
sb.append(key);
|
||||
sb.append(": ");
|
||||
sb.append(jo.getString(string));
|
||||
sb.append(jo.optString(key));
|
||||
sb.append(CRLF);
|
||||
}
|
||||
}
|
||||
|
||||
402
JSONArray.java
402
JSONArray.java
@@ -78,7 +78,7 @@ import java.util.Map;
|
||||
* </ul>
|
||||
*
|
||||
* @author JSON.org
|
||||
* @version 2016-07-19
|
||||
* @version 2016-08/15
|
||||
*/
|
||||
public class JSONArray implements Iterable<Object> {
|
||||
|
||||
@@ -154,8 +154,10 @@ public class JSONArray implements Iterable<Object> {
|
||||
* A Collection.
|
||||
*/
|
||||
public JSONArray(Collection<?> collection) {
|
||||
if (collection == null) {
|
||||
this.myArrayList = new ArrayList<Object>();
|
||||
if (collection != null) {
|
||||
} else {
|
||||
this.myArrayList = new ArrayList<Object>(collection.size());
|
||||
for (Object o: collection){
|
||||
this.myArrayList.add(JSONObject.wrap(o));
|
||||
}
|
||||
@@ -172,6 +174,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
this();
|
||||
if (array.getClass().isArray()) {
|
||||
int length = Array.getLength(array);
|
||||
this.myArrayList.ensureCapacity(length);
|
||||
for (int i = 0; i < length; i += 1) {
|
||||
this.put(JSONObject.wrap(Array.get(array, i)));
|
||||
}
|
||||
@@ -183,7 +186,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
|
||||
@Override
|
||||
public Iterator<Object> iterator() {
|
||||
return myArrayList.iterator();
|
||||
return this.myArrayList.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,15 +244,54 @@ public class JSONArray implements Iterable<Object> {
|
||||
public double getDouble(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).doubleValue();
|
||||
} else if (object instanceof String) {
|
||||
return Double.parseDouble((String) object);
|
||||
}
|
||||
return object instanceof Number ? ((Number) object).doubleValue()
|
||||
: Double.parseDouble((String) object);
|
||||
} catch (Exception e) {
|
||||
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the float value associated with a key.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public float getFloat(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).floatValue()
|
||||
: Float.parseFloat(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index
|
||||
+ "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Number value associated with a key.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public Number getNumber(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return (Number)object;
|
||||
}
|
||||
return JSONObject.stringToNumber(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,9 +312,8 @@ public class JSONArray implements Iterable<Object> {
|
||||
// JSONException should really take a throwable argument.
|
||||
// If it did, I would re-implement this with the Enum.valueOf
|
||||
// method and place any thrown exception in the JSONException
|
||||
throw new JSONException("JSONObject[" + JSONObject.quote(Integer.toString(index))
|
||||
+ "] is not an enum of type " + JSONObject.quote(clazz.getSimpleName())
|
||||
+ ".");
|
||||
throw new JSONException("JSONArray[" + index + "] is not an enum of type "
|
||||
+ JSONObject.quote(clazz.getSimpleName()) + ".");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@@ -293,7 +334,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return new BigDecimal(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index +
|
||||
"] could not convert to BigDecimal.");
|
||||
"] could not convert to BigDecimal.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +354,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return new BigInteger(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index +
|
||||
"] could not convert to BigInteger.");
|
||||
"] could not convert to BigInteger.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,15 +370,11 @@ public class JSONArray implements Iterable<Object> {
|
||||
public int getInt(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).intValue();
|
||||
} else if (object instanceof String) {
|
||||
return Integer.parseInt((String) object);
|
||||
}
|
||||
return object instanceof Number ? ((Number) object).intValue()
|
||||
: Integer.parseInt((String) object);
|
||||
} catch (Exception e) {
|
||||
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,15 +426,11 @@ public class JSONArray implements Iterable<Object> {
|
||||
public long getLong(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).longValue();
|
||||
} else if (object instanceof String) {
|
||||
return Long.parseLong((String) object);
|
||||
}
|
||||
return object instanceof Number ? ((Number) object).longValue()
|
||||
: Long.parseLong((String) object);
|
||||
} catch (Exception e) {
|
||||
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,7 +498,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
* Get the optional object value associated with an index.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* The index must be between 0 and length() - 1. If not, null is returned.
|
||||
* @return An object value, or null if there is no object at that index.
|
||||
*/
|
||||
public Object opt(int index) {
|
||||
@@ -498,20 +531,11 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(int index, boolean defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
try {
|
||||
return this.getBoolean(index);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (object.equals(Boolean.FALSE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("false"))) {
|
||||
return false;
|
||||
} else if (object.equals(Boolean.TRUE)
|
||||
|| (object instanceof String && ((String) object)
|
||||
.equalsIgnoreCase("true"))) {
|
||||
return true;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -539,18 +563,61 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index, double defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).doubleValue();
|
||||
} else if (object instanceof String) {
|
||||
return Double.parseDouble((String) object);
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).doubleValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Double.parseDouble((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional float value associated with an index. NaN is returned
|
||||
* if there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(int index) {
|
||||
return this.optFloat(index, Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional float value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(int index, float defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).floatValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Float.parseFloat((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -580,18 +647,20 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index, int defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).intValue();
|
||||
} else if (object instanceof String) {
|
||||
return Integer.parseInt((String) object);
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).intValue();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal(val.toString()).intValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -654,12 +723,29 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public BigInteger optBigInteger(int index, BigInteger defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof BigInteger){
|
||||
return (BigInteger) val;
|
||||
}
|
||||
if (val instanceof BigDecimal){
|
||||
return ((BigDecimal) val).toBigInteger();
|
||||
}
|
||||
if (val instanceof Double || val instanceof Float){
|
||||
return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
|
||||
}
|
||||
if (val instanceof Long || val instanceof Integer
|
||||
|| val instanceof Short || val instanceof Byte){
|
||||
return BigInteger.valueOf(((Number) val).longValue());
|
||||
}
|
||||
try {
|
||||
return new BigInteger(object.toString());
|
||||
final String valStr = val.toString();
|
||||
if(JSONObject.isDecimalNotation(valStr)) {
|
||||
return new BigDecimal(valStr).toBigInteger();
|
||||
}
|
||||
return new BigInteger(valStr);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -677,12 +763,25 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof BigDecimal){
|
||||
return (BigDecimal) val;
|
||||
}
|
||||
if (val instanceof BigInteger){
|
||||
return new BigDecimal((BigInteger) val);
|
||||
}
|
||||
if (val instanceof Double || val instanceof Float){
|
||||
return new BigDecimal(((Number) val).doubleValue());
|
||||
}
|
||||
if (val instanceof Long || val instanceof Integer
|
||||
|| val instanceof Short || val instanceof Byte){
|
||||
return new BigDecimal(((Number) val).longValue());
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(object.toString());
|
||||
return new BigDecimal(val.toString());
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -740,18 +839,65 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index, long defaultValue) {
|
||||
Object object = this.opt(index);
|
||||
if (JSONObject.NULL.equals(object)) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return ((Number) object).longValue();
|
||||
} else if (object instanceof String) {
|
||||
return Long.parseLong((String) object);
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).longValue();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal(val.toString()).longValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or <code>null</code>
|
||||
* if there is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(int index) {
|
||||
return this.optNumber(index, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or the default if there
|
||||
* is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(int index, Number defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return (Number) val;
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return JSONObject.stringToNumber((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
@@ -759,7 +905,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
/**
|
||||
* Get the optional string value associated with an index. It returns an
|
||||
* empty string if there is no value at that index. If the value is not a
|
||||
* string and is not null, then it is coverted to a string.
|
||||
* string and is not null, then it is converted to a string.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
@@ -1007,7 +1153,13 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
if (index < this.length()) {
|
||||
this.myArrayList.set(index, value);
|
||||
} else if(index == this.length()){
|
||||
// simple append
|
||||
this.put(value);
|
||||
} else {
|
||||
// if we are inserting past the length, we want to grow the array all at once
|
||||
// instead of incrementally.
|
||||
this.myArrayList.ensureCapacity(index + 1);
|
||||
while (index != this.length()) {
|
||||
this.put(JSONObject.NULL);
|
||||
}
|
||||
@@ -1036,7 +1188,30 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return the item matched by the JSONPointer, otherwise null
|
||||
*/
|
||||
public Object query(String jsonPointer) {
|
||||
return new JSONPointer(jsonPointer).queryFrom(this);
|
||||
return query(new JSONPointer(jsonPointer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a uaer initialized JSONPointer and tries to
|
||||
* match it to an item whithin this JSONArray. For example, given a
|
||||
* JSONArray initialized with this document:
|
||||
* <pre>
|
||||
* [
|
||||
* {"b":"c"}
|
||||
* ]
|
||||
* </pre>
|
||||
* and this JSONPointer:
|
||||
* <pre>
|
||||
* "/0/b"
|
||||
* </pre>
|
||||
* Then this method will return the String "c"
|
||||
* A JSONPointerException may be thrown from code called by this method.
|
||||
*
|
||||
* @param jsonPointer string that can be used to create a JSONPointer
|
||||
* @return the item matched by the JSONPointer, otherwise null
|
||||
*/
|
||||
public Object query(JSONPointer jsonPointer) {
|
||||
return jsonPointer.queryFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1048,9 +1223,20 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||
*/
|
||||
public Object optQuery(String jsonPointer) {
|
||||
JSONPointer pointer = new JSONPointer(jsonPointer);
|
||||
return optQuery(new JSONPointer(jsonPointer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries and returns a value from this object using {@code jsonPointer}, or
|
||||
* returns null if the query fails due to a missing key.
|
||||
*
|
||||
* @param jsonPointer The JSON pointer
|
||||
* @return the queried value or {@code null}
|
||||
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||
*/
|
||||
public Object optQuery(JSONPointer jsonPointer) {
|
||||
try {
|
||||
return pointer.queryFrom(this);
|
||||
return jsonPointer.queryFrom(this);
|
||||
} catch (JSONPointerException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -1086,8 +1272,14 @@ public class JSONArray implements Iterable<Object> {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < len; i += 1) {
|
||||
Object valueThis = this.get(i);
|
||||
Object valueOther = ((JSONArray)other).get(i);
|
||||
Object valueThis = this.myArrayList.get(i);
|
||||
Object valueOther = ((JSONArray)other).myArrayList.get(i);
|
||||
if(valueThis == valueOther) {
|
||||
return true;
|
||||
}
|
||||
if(valueThis == null) {
|
||||
return false;
|
||||
}
|
||||
if (valueThis instanceof JSONObject) {
|
||||
if (!((JSONObject)valueThis).similar(valueOther)) {
|
||||
return false;
|
||||
@@ -1119,7 +1311,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
if (names == null || names.length() == 0 || this.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
JSONObject jo = new JSONObject();
|
||||
JSONObject jo = new JSONObject(names.length());
|
||||
for (int i = 0; i < names.length(); i += 1) {
|
||||
jo.put(names.getString(i), this.opt(i));
|
||||
}
|
||||
@@ -1131,8 +1323,9 @@ public class JSONArray implements Iterable<Object> {
|
||||
* whitespace is added. If it is not possible to produce a syntactically
|
||||
* correct JSON text then null will be returned instead. This could occur if
|
||||
* the array contains an invalid number.
|
||||
* <p>
|
||||
* <p><b>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
* </b>
|
||||
*
|
||||
* @return a printable, displayable, transmittable representation of the
|
||||
* array.
|
||||
@@ -1147,8 +1340,23 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a prettyprinted JSON text of this JSONArray. Warning: This method
|
||||
* assumes that the data structure is acyclical.
|
||||
* Make a pretty-printed JSON text of this JSONArray.
|
||||
*
|
||||
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
|
||||
* one element, then the array will be output on a single line:
|
||||
* <pre>{@code [1]}</pre>
|
||||
*
|
||||
* <p>If an array has 2 or more elements, then it will be output across
|
||||
* multiple lines: <pre>{@code
|
||||
* [
|
||||
* 1,
|
||||
* "value 2",
|
||||
* 3
|
||||
* ]
|
||||
* }</pre>
|
||||
* <p><b>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
* </b>
|
||||
*
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
@@ -1168,8 +1376,9 @@ public class JSONArray implements Iterable<Object> {
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* <p><b>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
*</b>
|
||||
*
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
@@ -1179,17 +1388,30 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the JSONArray as JSON text to a writer. For
|
||||
* compactness, no whitespace is added.
|
||||
* <p>
|
||||
* Write the contents of the JSONArray as JSON text to a writer.
|
||||
*
|
||||
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
|
||||
* one element, then the array will be output on a single line:
|
||||
* <pre>{@code [1]}</pre>
|
||||
*
|
||||
* <p>If an array has 2 or more elements, then it will be output across
|
||||
* multiple lines: <pre>{@code
|
||||
* [
|
||||
* 1,
|
||||
* "value 2",
|
||||
* 3
|
||||
* ]
|
||||
* }</pre>
|
||||
* <p><b>
|
||||
* Warning: This method assumes that the data structure is acyclical.
|
||||
* </b>
|
||||
*
|
||||
* @param writer
|
||||
* Writes the serialized JSON
|
||||
* @param indentFactor
|
||||
* The number of spaces to add to each level of indentation.
|
||||
* @param indent
|
||||
* The indention of the top level.
|
||||
* The indentation of the top level.
|
||||
* @return The writer.
|
||||
* @throws JSONException
|
||||
*/
|
||||
@@ -1201,8 +1423,12 @@ public class JSONArray implements Iterable<Object> {
|
||||
writer.write('[');
|
||||
|
||||
if (length == 1) {
|
||||
try {
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(0),
|
||||
indentFactor, indent);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("Unable to write JSONArray value at index: 0", e);
|
||||
}
|
||||
} else if (length != 0) {
|
||||
final int newindent = indent + indentFactor;
|
||||
|
||||
@@ -1214,8 +1440,12 @@ public class JSONArray implements Iterable<Object> {
|
||||
writer.write('\n');
|
||||
}
|
||||
JSONObject.indent(writer, newindent);
|
||||
try {
|
||||
JSONObject.writeValue(writer, this.myArrayList.get(i),
|
||||
indentFactor, newindent);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("Unable to write JSONArray value at index: " + i, e);
|
||||
}
|
||||
commanate = true;
|
||||
}
|
||||
if (indentFactor > 0) {
|
||||
|
||||
36
JSONML.java
36
JSONML.java
@@ -1,5 +1,7 @@
|
||||
package org.json;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/*
|
||||
Copyright (c) 2008 JSON.org
|
||||
|
||||
@@ -24,9 +26,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* This provides static methods to convert an XML text into a JSONArray or
|
||||
* JSONObject, and to covert a JSONArray or JSONObject into an XML text using
|
||||
@@ -42,7 +41,7 @@ public class JSONML {
|
||||
* @param arrayForm true if array form, false if object form.
|
||||
* @param ja The JSONArray that is containing the current tag or null
|
||||
* if we are at the outermost level.
|
||||
* @param keepStrings Don't type-convert text nodes and attibute values
|
||||
* @param keepStrings Don't type-convert text nodes and attribute values
|
||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||
* @throws JSONException
|
||||
*/
|
||||
@@ -175,7 +174,7 @@ public class JSONML {
|
||||
if (!(token instanceof String)) {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
newjo.accumulate(attribute, keepStrings ? token :JSONObject.stringToValue((String)token));
|
||||
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
|
||||
token = null;
|
||||
} else {
|
||||
newjo.accumulate(attribute, "");
|
||||
@@ -226,7 +225,7 @@ public class JSONML {
|
||||
} else {
|
||||
if (ja != null) {
|
||||
ja.put(token instanceof String
|
||||
? keepStrings ? token :JSONObject.stringToValue((String)token)
|
||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
||||
: token);
|
||||
}
|
||||
}
|
||||
@@ -397,13 +396,10 @@ public class JSONML {
|
||||
public static String toString(JSONArray ja) throws JSONException {
|
||||
int i;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String tagName;
|
||||
String value;
|
||||
|
||||
// Emit <tagName
|
||||
|
||||
@@ -420,17 +416,16 @@ public class JSONML {
|
||||
|
||||
// Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
for (final Entry<String, ?> entry : jo.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
final Object value = entry.getValue();
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append(XML.escape(value.toString()));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
@@ -482,12 +477,10 @@ public class JSONML {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i;
|
||||
JSONArray ja;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
int length;
|
||||
Object object;
|
||||
String tagName;
|
||||
String value;
|
||||
Object value;
|
||||
|
||||
//Emit <tagName
|
||||
|
||||
@@ -502,18 +495,17 @@ public class JSONML {
|
||||
|
||||
//Emit the attributes
|
||||
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
for (final Entry<String, ?> entry : jo.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
if (!"tagName".equals(key) && !"childNodes".equals(key)) {
|
||||
XML.noSpace(key);
|
||||
value = jo.optString(key);
|
||||
value = entry.getValue();
|
||||
if (value != null) {
|
||||
sb.append(' ');
|
||||
sb.append(XML.escape(key));
|
||||
sb.append('=');
|
||||
sb.append('"');
|
||||
sb.append(XML.escape(value));
|
||||
sb.append(XML.escape(value.toString()));
|
||||
sb.append('"');
|
||||
}
|
||||
}
|
||||
|
||||
813
JSONObject.java
813
JSONObject.java
File diff suppressed because it is too large
Load Diff
@@ -68,11 +68,11 @@ public class JSONPointer {
|
||||
* {@link #append(String)} method calls.
|
||||
*/
|
||||
public JSONPointer build() {
|
||||
return new JSONPointer(refTokens);
|
||||
return new JSONPointer(this.refTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an arbitary token to the list of reference tokens. It can be any non-null value.
|
||||
* 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
|
||||
@@ -87,7 +87,7 @@ public class JSONPointer {
|
||||
if (token == null) {
|
||||
throw new NullPointerException("token cannot be null");
|
||||
}
|
||||
refTokens.add(token);
|
||||
this.refTokens.add(token);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class JSONPointer {
|
||||
* @return {@code this}
|
||||
*/
|
||||
public Builder append(int arrayIndex) {
|
||||
refTokens.add(String.valueOf(arrayIndex));
|
||||
this.refTokens.add(String.valueOf(arrayIndex));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -134,29 +134,30 @@ public class JSONPointer {
|
||||
* @param pointer the JSON String or URI Fragment representation of the JSON pointer.
|
||||
* @throws IllegalArgumentException if {@code pointer} is not a valid JSON pointer
|
||||
*/
|
||||
public JSONPointer(String pointer) {
|
||||
public JSONPointer(final String pointer) {
|
||||
if (pointer == null) {
|
||||
throw new NullPointerException("pointer cannot be null");
|
||||
}
|
||||
if (pointer.isEmpty()) {
|
||||
refTokens = Collections.emptyList();
|
||||
if (pointer.isEmpty() || pointer.equals("#")) {
|
||||
this.refTokens = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
String refs;
|
||||
if (pointer.startsWith("#/")) {
|
||||
pointer = pointer.substring(2);
|
||||
refs = pointer.substring(2);
|
||||
try {
|
||||
pointer = URLDecoder.decode(pointer, ENCODING);
|
||||
refs = URLDecoder.decode(refs, ENCODING);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (pointer.startsWith("/")) {
|
||||
pointer = pointer.substring(1);
|
||||
refs = pointer.substring(1);
|
||||
} else {
|
||||
throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'");
|
||||
}
|
||||
refTokens = new ArrayList<String>();
|
||||
for (String token : pointer.split("/")) {
|
||||
refTokens.add(unescape(token));
|
||||
this.refTokens = new ArrayList<String>();
|
||||
for (String token : refs.split("/")) {
|
||||
this.refTokens.add(unescape(token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,11 +182,11 @@ public class JSONPointer {
|
||||
* @throws JSONPointerException if an error occurs during evaluation
|
||||
*/
|
||||
public Object queryFrom(Object document) {
|
||||
if (refTokens.isEmpty()) {
|
||||
if (this.refTokens.isEmpty()) {
|
||||
return document;
|
||||
}
|
||||
Object current = document;
|
||||
for (String token : refTokens) {
|
||||
for (String token : this.refTokens) {
|
||||
if (current instanceof JSONObject) {
|
||||
current = ((JSONObject) current).opt(unescape(token));
|
||||
} else if (current instanceof JSONArray) {
|
||||
@@ -206,6 +207,7 @@ public class JSONPointer {
|
||||
* @return the matched object. If no matching item is found a
|
||||
* JSONPointerException is thrown
|
||||
*/
|
||||
@SuppressWarnings("boxing")
|
||||
private Object readByIndexToken(Object current, String indexToken) {
|
||||
try {
|
||||
int index = Integer.parseInt(indexToken);
|
||||
@@ -227,7 +229,7 @@ public class JSONPointer {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder rval = new StringBuilder("");
|
||||
for (String token: refTokens) {
|
||||
for (String token: this.refTokens) {
|
||||
rval.append('/').append(escape(token));
|
||||
}
|
||||
return rval.toString();
|
||||
@@ -255,7 +257,7 @@ public class JSONPointer {
|
||||
public String toURIFragment() {
|
||||
try {
|
||||
StringBuilder rval = new StringBuilder("#");
|
||||
for (String token : refTokens) {
|
||||
for (String token : this.refTokens) {
|
||||
rval.append('/').append(URLEncoder.encode(token, ENCODING));
|
||||
}
|
||||
return rval.toString();
|
||||
|
||||
@@ -72,6 +72,7 @@ public class JSONStringer extends JSONWriter {
|
||||
* <code>endArray</code>).
|
||||
* @return The JSON text.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.mode == 'd' ? this.writer.toString() : null;
|
||||
}
|
||||
|
||||
102
JSONTokener.java
102
JSONTokener.java
@@ -39,18 +39,26 @@ SOFTWARE.
|
||||
* @version 2014-05-03
|
||||
*/
|
||||
public class JSONTokener {
|
||||
|
||||
/** current read character position on the current line. */
|
||||
private long character;
|
||||
/** flag to indicate if the end of the input has been found. */
|
||||
private boolean eof;
|
||||
/** current read index of the input. */
|
||||
private long index;
|
||||
/** current line of the input. */
|
||||
private long line;
|
||||
/** previous character read from the input. */
|
||||
private char previous;
|
||||
private Reader reader;
|
||||
/** 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;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from a Reader.
|
||||
* Construct a JSONTokener from a Reader. The caller must close the Reader.
|
||||
*
|
||||
* @param reader A reader.
|
||||
*/
|
||||
@@ -63,12 +71,13 @@ public class JSONTokener {
|
||||
this.previous = 0;
|
||||
this.index = 0;
|
||||
this.character = 1;
|
||||
this.characterPreviousLine = 0;
|
||||
this.line = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a JSONTokener from an InputStream.
|
||||
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
|
||||
* @param inputStream The source.
|
||||
*/
|
||||
public JSONTokener(InputStream inputStream) {
|
||||
@@ -97,12 +106,23 @@ public class JSONTokener {
|
||||
if (this.usePrevious || this.index <= 0) {
|
||||
throw new JSONException("Stepping back two steps is not supported");
|
||||
}
|
||||
this.index -= 1;
|
||||
this.character -= 1;
|
||||
this.decrementIndexes();
|
||||
this.usePrevious = true;
|
||||
this.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--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hex value of a character (base16).
|
||||
@@ -124,6 +144,8 @@ public class JSONTokener {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
@@ -139,11 +161,24 @@ public class JSONTokener {
|
||||
* or backward while checking for more data.
|
||||
*/
|
||||
public boolean more() throws JSONException {
|
||||
this.next();
|
||||
if (this.end()) {
|
||||
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.back();
|
||||
this.reader.reset();
|
||||
} catch (IOException e) {
|
||||
throw new JSONException("Unable to read the next character from the stream", e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -165,26 +200,39 @@ public class JSONTokener {
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
if (c <= 0) { // End of stream
|
||||
this.eof = true;
|
||||
c = 0;
|
||||
}
|
||||
}
|
||||
this.index += 1;
|
||||
if (this.previous == '\r') {
|
||||
this.line += 1;
|
||||
this.character = c == '\n' ? 0 : 1;
|
||||
} else if (c == '\n') {
|
||||
this.line += 1;
|
||||
this.character = 0;
|
||||
} else {
|
||||
this.character += 1;
|
||||
return 0;
|
||||
}
|
||||
this.incrementIndexes(c);
|
||||
this.previous = (char) c;
|
||||
return this.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;
|
||||
}
|
||||
this.character=0;
|
||||
} else {
|
||||
this.character++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume the next character, and check that it matches a specified
|
||||
@@ -196,9 +244,12 @@ public class JSONTokener {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -426,13 +477,17 @@ public class JSONTokener {
|
||||
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 c;
|
||||
return 0;
|
||||
}
|
||||
} while (c != to);
|
||||
this.reader.mark(1);
|
||||
} catch (IOException exception) {
|
||||
throw new JSONException(exception);
|
||||
}
|
||||
@@ -440,7 +495,6 @@ public class JSONTokener {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a JSONException to signal a syntax error.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 JSON.org
|
||||
@@ -50,11 +49,11 @@ SOFTWARE.
|
||||
* <p>
|
||||
* The first method called must be <code>array</code> or <code>object</code>.
|
||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
||||
* you. Objects and arrays can be nested up to 200 levels deep.
|
||||
* <p>
|
||||
* This can sometimes be easier than using a JSONObject to build a string.
|
||||
* @author JSON.org
|
||||
* @version 2015-12-09
|
||||
* @version 2016-08-08
|
||||
*/
|
||||
public class JSONWriter {
|
||||
private static final int maxdepth = 200;
|
||||
@@ -88,12 +87,12 @@ public class JSONWriter {
|
||||
/**
|
||||
* The writer that will receive the output.
|
||||
*/
|
||||
protected Writer writer;
|
||||
protected Appendable writer;
|
||||
|
||||
/**
|
||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||
*/
|
||||
public JSONWriter(Writer w) {
|
||||
public JSONWriter(Appendable w) {
|
||||
this.comma = false;
|
||||
this.mode = 'i';
|
||||
this.stack = new JSONObject[maxdepth];
|
||||
@@ -114,9 +113,9 @@ public class JSONWriter {
|
||||
if (this.mode == 'o' || this.mode == 'a') {
|
||||
try {
|
||||
if (this.comma && this.mode == 'a') {
|
||||
this.writer.write(',');
|
||||
this.writer.append(',');
|
||||
}
|
||||
this.writer.write(string);
|
||||
this.writer.append(string);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
@@ -150,20 +149,20 @@ public class JSONWriter {
|
||||
|
||||
/**
|
||||
* End something.
|
||||
* @param mode Mode
|
||||
* @param m Mode
|
||||
* @param c Closing character
|
||||
* @return this
|
||||
* @throws JSONException If unbalanced.
|
||||
*/
|
||||
private JSONWriter end(char mode, char c) throws JSONException {
|
||||
if (this.mode != mode) {
|
||||
throw new JSONException(mode == 'a'
|
||||
private JSONWriter end(char m, char c) throws JSONException {
|
||||
if (this.mode != m) {
|
||||
throw new JSONException(m == 'a'
|
||||
? "Misplaced endArray."
|
||||
: "Misplaced endObject.");
|
||||
}
|
||||
this.pop(mode);
|
||||
this.pop(m);
|
||||
try {
|
||||
this.writer.write(c);
|
||||
this.writer.append(c);
|
||||
} catch (IOException e) {
|
||||
throw new JSONException(e);
|
||||
}
|
||||
@@ -207,10 +206,10 @@ public class JSONWriter {
|
||||
try {
|
||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
||||
if (this.comma) {
|
||||
this.writer.write(',');
|
||||
this.writer.append(',');
|
||||
}
|
||||
this.writer.write(JSONObject.quote(string));
|
||||
this.writer.write(':');
|
||||
this.writer.append(JSONObject.quote(string));
|
||||
this.writer.append(':');
|
||||
this.comma = false;
|
||||
this.mode = 'o';
|
||||
return this;
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,3 +1,5 @@
|
||||
============================================================================
|
||||
|
||||
Copyright (c) 2002 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
||||
@@ -25,7 +25,7 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ public class Property {
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
|
||||
JSONObject jo = new JSONObject();
|
||||
JSONObject jo = new JSONObject(properties == null ? 0 : properties.size());
|
||||
if (properties != null && !properties.isEmpty()) {
|
||||
Enumeration<?> enumProperties = properties.propertyNames();
|
||||
while(enumProperties.hasMoreElements()) {
|
||||
@@ -61,10 +61,11 @@ public class Property {
|
||||
public static Properties toProperties(JSONObject jo) throws JSONException {
|
||||
Properties properties = new Properties();
|
||||
if (jo != null) {
|
||||
Iterator<String> keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
String name = keys.next();
|
||||
properties.put(name, jo.getString(name));
|
||||
for (final Entry<String, ?> entry : jo.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (!JSONObject.NULL.equals(value)) {
|
||||
properties.put(entry.getKey(), value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
|
||||
11
README
11
README
@@ -22,7 +22,7 @@ JSONObject.java: The JSONObject can parse text from a String or a JSONTokener
|
||||
to produce a map-like object. The object provides methods for manipulating its
|
||||
contents, and for producing a JSON compliant object serialization.
|
||||
|
||||
JSONArray.java: The JSONObject can parse text from a String or a JSONTokener
|
||||
JSONArray.java: The JSONArray can parse text from a String or a JSONTokener
|
||||
to produce a vector-like object. The object provides methods for manipulating
|
||||
its contents, and for producing a JSON compliant array serialization.
|
||||
|
||||
@@ -89,8 +89,15 @@ invalid number formats (1.2e6.3) will cause errors as such documents can not be
|
||||
reliably.
|
||||
|
||||
Release history:
|
||||
20171018 Checkpoint for recent commits.
|
||||
|
||||
20160807 Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(),
|
||||
20170516 Roll up recent commits.
|
||||
|
||||
20160810 Revert code that was breaking opt*() methods.
|
||||
|
||||
20160807 This release contains a bug in the JSONObject.opt*() and JSONArray.opt*() methods,
|
||||
it is not recommended for use.
|
||||
Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(),
|
||||
RFC4180 compatibility, JSONPointer, some exception fixes, optional XML type conversion.
|
||||
Contains the latest code as of 7 Aug, 2016
|
||||
|
||||
|
||||
147
XML.java
147
XML.java
@@ -25,17 +25,17 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* 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-01-30
|
||||
* @version 2016-08-10
|
||||
*/
|
||||
@SuppressWarnings("boxing")
|
||||
public class XML {
|
||||
|
||||
/** The Character '&'. */
|
||||
public static final Character AMP = '&';
|
||||
|
||||
@@ -63,6 +63,46 @@ public class XML {
|
||||
/** The Character '/'. */
|
||||
public static final Character SLASH = '/';
|
||||
|
||||
/**
|
||||
* Creates an iterator for navigating Code Points in a string instead of
|
||||
* characters. Once Java7 support is dropped, this can be replaced with
|
||||
* <code>
|
||||
* string.codePoints()
|
||||
* </code>
|
||||
* which is available in Java8 and above.
|
||||
*
|
||||
* @see <a href=
|
||||
* "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
|
||||
*/
|
||||
private static Iterable<Integer> codePointIterator(final String string) {
|
||||
return new Iterable<Integer>() {
|
||||
@Override
|
||||
public Iterator<Integer> iterator() {
|
||||
return new Iterator<Integer>() {
|
||||
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:
|
||||
*
|
||||
@@ -71,6 +111,7 @@ public class XML {
|
||||
* < <small>(less than)</small> is replaced by &lt;
|
||||
* > <small>(greater than)</small> is replaced by &gt;
|
||||
* " <small>(double quote)</small> is replaced by &quot;
|
||||
* ' <small>(single quote / apostrophe)</small> is replaced by &apos;
|
||||
* </pre>
|
||||
*
|
||||
* @param string
|
||||
@@ -79,9 +120,8 @@ public class XML {
|
||||
*/
|
||||
public static String escape(String string) {
|
||||
StringBuilder sb = new StringBuilder(string.length());
|
||||
for (int i = 0, length = string.length(); i < length; i++) {
|
||||
char c = string.charAt(i);
|
||||
switch (c) {
|
||||
for (final int cp : codePointIterator(string)) {
|
||||
switch (cp) {
|
||||
case '&':
|
||||
sb.append("&");
|
||||
break;
|
||||
@@ -98,6 +138,69 @@ public class XML {
|
||||
sb.append("'");
|
||||
break;
|
||||
default:
|
||||
if (mustEscape(cp)) {
|
||||
sb.append("&#x");
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -227,7 +330,6 @@ public class XML {
|
||||
if (token == null) {
|
||||
token = x.nextToken();
|
||||
}
|
||||
|
||||
// attribute = value
|
||||
if (token instanceof String) {
|
||||
string = (String) token;
|
||||
@@ -238,7 +340,7 @@ public class XML {
|
||||
throw x.syntaxError("Missing value");
|
||||
}
|
||||
jsonobject.accumulate(string,
|
||||
keepStrings ? token : JSONObject.stringToValue((String) token));
|
||||
keepStrings ? ((String)token) : stringToValue((String) token));
|
||||
token = null;
|
||||
} else {
|
||||
jsonobject.accumulate(string, "");
|
||||
@@ -270,7 +372,7 @@ public class XML {
|
||||
string = (String) token;
|
||||
if (string.length() > 0) {
|
||||
jsonobject.accumulate("content",
|
||||
keepStrings ? token : JSONObject.stringToValue(string));
|
||||
keepStrings ? string : stringToValue(string));
|
||||
}
|
||||
|
||||
} else if (token == LT) {
|
||||
@@ -297,14 +399,12 @@ public class XML {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method has been deprecated in favor of the
|
||||
* {@link JSONObject.stringToValue(String)} method. Use it instead.
|
||||
* This method is the same as {@link JSONObject#stringToValue(String)}
|
||||
* except that this also tries to unescape String values.
|
||||
*
|
||||
* @deprecated Use {@link JSONObject#stringToValue(String)} instead.
|
||||
* @param string String to convert
|
||||
* @return JSON value of this string or the string
|
||||
*/
|
||||
@Deprecated
|
||||
public static Object stringToValue(String string) {
|
||||
return JSONObject.stringToValue(string);
|
||||
}
|
||||
@@ -381,15 +481,12 @@ public class XML {
|
||||
* @return A string.
|
||||
* @throws JSONException Thrown if there is an error parsing the string
|
||||
*/
|
||||
public static String toString(Object object, String tagName)
|
||||
public static String toString(final Object object, final String tagName)
|
||||
throws JSONException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
JSONArray ja;
|
||||
JSONObject jo;
|
||||
String key;
|
||||
Iterator<String> keys;
|
||||
String string;
|
||||
Object value;
|
||||
|
||||
if (object instanceof JSONObject) {
|
||||
|
||||
@@ -402,16 +499,14 @@ public class XML {
|
||||
|
||||
// Loop thru the keys.
|
||||
jo = (JSONObject) object;
|
||||
keys = jo.keys();
|
||||
while (keys.hasNext()) {
|
||||
key = keys.next();
|
||||
value = jo.opt(key);
|
||||
for (final Entry<String, ?> entry : jo.entrySet()) {
|
||||
final String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
value = "";
|
||||
} else if (value.getClass().isArray()) {
|
||||
value = new JSONArray(value);
|
||||
}
|
||||
string = value instanceof String ? (String) value : null;
|
||||
|
||||
// Emit content in body
|
||||
if ("content".equals(key)) {
|
||||
@@ -468,13 +563,12 @@ public class XML {
|
||||
|
||||
}
|
||||
|
||||
if (object != null) {
|
||||
if (object != null && (object instanceof JSONArray || object.getClass().isArray())) {
|
||||
if(object.getClass().isArray()) {
|
||||
object = new JSONArray(object);
|
||||
}
|
||||
|
||||
if (object instanceof JSONArray) {
|
||||
ja = new JSONArray(object);
|
||||
} else {
|
||||
ja = (JSONArray) object;
|
||||
}
|
||||
for (Object val : ja) {
|
||||
// XML does not have good support for arrays. If an array
|
||||
// appears in a place where XML is lacking, synthesize an
|
||||
@@ -483,7 +577,6 @@ public class XML {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
string = (object == null) ? "null" : escape(object.toString());
|
||||
return (tagName == null) ? "\"" + string + "\""
|
||||
|
||||
@@ -64,11 +64,8 @@ public class XMLTokener extends JSONTokener {
|
||||
char c;
|
||||
int i;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (;;) {
|
||||
while (more()) {
|
||||
c = next();
|
||||
if (end()) {
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
sb.append(c);
|
||||
i = sb.length() - 3;
|
||||
if (i >= 0 && sb.charAt(i) == ']' &&
|
||||
@@ -77,6 +74,7 @@ public class XMLTokener extends JSONTokener {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
throw syntaxError("Unclosed CDATA");
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +101,10 @@ public class XMLTokener extends JSONTokener {
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
for (;;) {
|
||||
if (c == '<' || c == 0) {
|
||||
if (c == 0) {
|
||||
return sb.toString().trim();
|
||||
}
|
||||
if (c == '<') {
|
||||
back();
|
||||
return sb.toString().trim();
|
||||
}
|
||||
@@ -137,8 +138,37 @@ public class XMLTokener extends JSONTokener {
|
||||
}
|
||||
}
|
||||
String string = sb.toString();
|
||||
Object object = entity.get(string);
|
||||
return object != null ? object : ampersand + string + ";";
|
||||
return unescapeEntity(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unescapes 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') {
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user