1
0
Fork 0
mirror of https://github.com/ethauvin/JSON-java.git synced 2025-06-17 07:50:52 -07:00

Updates for supporting the Android API

This commit is contained in:
John J. Aylward 2017-06-21 11:52:15 -04:00
parent 5024f2d210
commit e8b1b66888
9 changed files with 198 additions and 101 deletions

View file

@ -1,7 +1,5 @@
package org.json; package org.json;
import java.util.Map.Entry;
/* /*
Copyright (c) 2002 JSON.org Copyright (c) 2002 JSON.org
@ -69,10 +67,10 @@ public class CookieList {
*/ */
public static String toString(JSONObject jo) throws JSONException { public static String toString(JSONObject jo) throws JSONException {
boolean b = false; boolean b = false;
StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
for (final Entry<String,?> entry : jo.entrySet()) { // Don't use the new entrySet API to maintain Android support
final String key = entry.getKey(); for (final String key : jo.keySet()) {
final Object value = entry.getValue(); final Object value = jo.opt(key);
if (!JSONObject.NULL.equals(value)) { if (!JSONObject.NULL.equals(value)) {
if (b) { if (b) {
sb.append(';'); sb.append(';');

View file

@ -25,7 +25,6 @@ SOFTWARE.
*/ */
import java.util.Locale; import java.util.Locale;
import java.util.Map.Entry;
/** /**
* Convert an HTTP header to a JSONObject and back. * Convert an HTTP header to a JSONObject and back.
@ -145,11 +144,12 @@ public class HTTP {
throw new JSONException("Not enough material for an HTTP header."); throw new JSONException("Not enough material for an HTTP header.");
} }
sb.append(CRLF); sb.append(CRLF);
for (final Entry<String,?> entry : jo.entrySet()) { // Don't use the new entrySet API to maintain Android support
final String key = entry.getKey(); for (final String key : jo.keySet()) {
String value = jo.optString(key);
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) && if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
!"Reason-Phrase".equals(key) && !"Method".equals(key) && !"Reason-Phrase".equals(key) && !"Method".equals(key) &&
!"Request-URI".equals(key) && !JSONObject.NULL.equals(entry.getValue())) { !"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
sb.append(key); sb.append(key);
sb.append(": "); sb.append(": ");
sb.append(jo.optString(key)); sb.append(jo.optString(key));

View file

@ -1,7 +1,5 @@
package org.json; package org.json;
import java.util.Map.Entry;
/* /*
Copyright (c) 2008 JSON.org Copyright (c) 2008 JSON.org
@ -416,10 +414,10 @@ public class JSONML {
// Emit the attributes // Emit the attributes
for (final Entry<String, ?> entry : jo.entrySet()) { // Don't use the new entrySet API to maintain Android support
final String key = entry.getKey(); for (final String key : jo.keySet()) {
final Object value = jo.opt(key);
XML.noSpace(key); XML.noSpace(key);
final Object value = entry.getValue();
if (value != null) { if (value != null) {
sb.append(' '); sb.append(' ');
sb.append(XML.escape(key)); sb.append(XML.escape(key));
@ -495,11 +493,11 @@ public class JSONML {
//Emit the attributes //Emit the attributes
for (final Entry<String, ?> entry : jo.entrySet()) { // Don't use the new entrySet API to maintain Android support
final String key = entry.getKey(); for (final String key : jo.keySet()) {
if (!"tagName".equals(key) && !"childNodes".equals(key)) { if (!"tagName".equals(key) && !"childNodes".equals(key)) {
XML.noSpace(key); XML.noSpace(key);
value = entry.getValue(); value = jo.opt(key);
if (value != null) { if (value != null) {
sb.append(' '); sb.append(' ');
sb.append(XML.escape(key)); sb.append(XML.escape(key));

View file

@ -1908,6 +1908,8 @@ public class JSONObject {
* A String. * A String.
* @return A simple JSON value. * @return A simple JSON value.
*/ */
// Changes to this method must be copied to the corresponding method in
// the XML class to keep full support for Android
public static Object stringToValue(String string) { public static Object stringToValue(String string) {
if (string.equals("")) { if (string.equals("")) {
return string; return string;
@ -2065,55 +2067,11 @@ public class JSONObject {
* If the value is or contains an invalid number. * If the value is or contains an invalid number.
*/ */
public static String valueToString(Object value) throws JSONException { public static String valueToString(Object value) throws JSONException {
if (value == null || value.equals(null)) { // moves the implementation to JSONWriter as:
return "null"; // 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
if (value instanceof JSONString) { // Android users can use the writer with the built in Android JSONObject implementation.
Object object; return JSONWriter.valueToString(value);
try {
object = ((JSONString) value).toJSONString();
} catch (Exception e) {
throw new JSONException(e);
}
if (object instanceof String) {
return (String) object;
}
throw new JSONException("Bad value from toJSONString: " + object);
}
if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
final String numberAsString = numberToString((Number) value);
try {
// Use the BigDecimal constructor for it's parser to validate the format.
@SuppressWarnings("unused")
BigDecimal unused = new BigDecimal(numberAsString);
// Close enough to a JSON number that we will return it unquoted
return numberAsString;
} catch (NumberFormatException ex){
// The Number value is not a valid JSON number.
// Instead we will quote it as a string
return quote(numberAsString);
}
}
if (value instanceof Boolean || value instanceof JSONObject
|| value instanceof JSONArray) {
return value.toString();
}
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
return new JSONObject(map).toString();
}
if (value instanceof Collection) {
Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
}
if (value.getClass().isArray()) {
return new JSONArray(value).toString();
}
if(value instanceof Enum<?>){
return quote(((Enum<?>)value).name());
}
return quote(value.toString());
} }
/** /**

View file

@ -5,7 +5,9 @@ import static java.lang.String.format;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/* /*
Copyright (c) 2002 JSON.org Copyright (c) 2002 JSON.org
@ -181,7 +183,7 @@ public class JSONPointer {
* @return the result of the evaluation * @return the result of the evaluation
* @throws JSONPointerException if an error occurs during evaluation * @throws JSONPointerException if an error occurs during evaluation
*/ */
public Object queryFrom(Object document) { public Object queryFrom(Object document) throws JSONPointerException {
if (this.refTokens.isEmpty()) { if (this.refTokens.isEmpty()) {
return document; return document;
} }
@ -205,10 +207,9 @@ public class JSONPointer {
* @param current the JSONArray to be evaluated * @param current the JSONArray to be evaluated
* @param indexToken the array index in string form * @param indexToken the array index in string form
* @return the matched object. If no matching item is found a * @return the matched object. If no matching item is found a
* JSONPointerException is thrown * @throws JSONPointerException is thrown if the index is out of bounds
*/ */
@SuppressWarnings("boxing") private Object readByIndexToken(Object current, String indexToken) throws JSONPointerException {
private Object readByIndexToken(Object current, String indexToken) {
try { try {
int index = Integer.parseInt(indexToken); int index = Integer.parseInt(indexToken);
JSONArray currentArr = (JSONArray) current; JSONArray currentArr = (JSONArray) current;
@ -216,7 +217,11 @@ public class JSONPointer {
throw new JSONPointerException(format("index %d is out of bounds - the array has %d elements", index, throw new JSONPointerException(format("index %d is out of bounds - the array has %d elements", index,
currentArr.length())); currentArr.length()));
} }
try {
return currentArr.get(index); return currentArr.get(index);
} catch (JSONException e) {
throw new JSONPointerException("Error reading value at index position " + index, e);
}
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new JSONPointerException(format("%s is not an array index", indexToken), e); throw new JSONPointerException(format("%s is not an array index", indexToken), e);
} }

View file

@ -1,6 +1,9 @@
package org.json; package org.json;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
/* /*
Copyright (c) 2006 JSON.org Copyright (c) 2006 JSON.org
@ -117,6 +120,9 @@ public class JSONWriter {
} }
this.writer.append(string); this.writer.append(string);
} catch (IOException e) { } 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(e);
} }
if (this.mode == 'o') { if (this.mode == 'o') {
@ -164,6 +170,9 @@ public class JSONWriter {
try { try {
this.writer.append(c); this.writer.append(c);
} catch (IOException e) { } 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(e);
} }
this.comma = true; this.comma = true;
@ -204,7 +213,12 @@ public class JSONWriter {
} }
if (this.mode == 'k') { if (this.mode == 'k') {
try { try {
this.stack[this.top - 1].putOnce(string, Boolean.TRUE); 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) { if (this.comma) {
this.writer.append(','); this.writer.append(',');
} }
@ -214,6 +228,9 @@ public class JSONWriter {
this.mode = 'o'; this.mode = 'o';
return this; return this;
} catch (IOException e) { } 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(e);
} }
} }
@ -280,6 +297,81 @@ public class JSONWriter {
this.top += 1; 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
* JSON text. The method is required to produce a strictly conforming text.
* If the object does not contain a toJSONString method (which is the most
* common case), then a text will be produced by other means. If the value
* is an array or Collection, then a JSONArray will be made from it and its
* toJSONString method will be called. If the value is a MAP, then a
* JSONObject will be made from it and its toJSONString method will be
* called. Otherwise, the value's toString method will be called, and the
* result will be quoted.
*
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @param value
* The value to be serialized.
* @return a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
* @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)) {
return "null";
}
if (value instanceof JSONString) {
Object object;
try {
object = ((JSONString) value).toJSONString();
} catch (Exception e) {
throw new JSONException(e);
}
if (object instanceof String) {
return (String) object;
}
throw new JSONException("Bad value from toJSONString: " + object);
}
if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
final String numberAsString = JSONObject.numberToString((Number) value);
try {
// Use the BigDecimal constructor for it's parser to validate the format.
@SuppressWarnings("unused")
BigDecimal unused = new BigDecimal(numberAsString);
// Close enough to a JSON number that we will return it unquoted
return numberAsString;
} catch (NumberFormatException ex){
// The Number value is not a valid JSON number.
// Instead we will quote it as a string
return JSONObject.quote(numberAsString);
}
}
if (value instanceof Boolean || value instanceof JSONObject
|| value instanceof JSONArray) {
return value.toString();
}
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
return new JSONObject(map).toString();
}
if (value instanceof Collection) {
Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
}
if (value.getClass().isArray()) {
return new JSONArray(value).toString();
}
if(value instanceof Enum<?>){
return JSONObject.quote(((Enum<?>)value).name());
}
return JSONObject.quote(value.toString());
}
/** /**
* Append either the value <code>true</code> or the value * Append either the value <code>true</code> or the value
@ -321,6 +413,6 @@ public class JSONWriter {
* @throws JSONException If the value is out of sequence. * @throws JSONException If the value is out of sequence.
*/ */
public JSONWriter value(Object object) throws JSONException { public JSONWriter value(Object object) throws JSONException {
return this.append(JSONObject.valueToString(object)); return this.append(valueToString(object));
} }
} }

View file

@ -25,7 +25,6 @@ SOFTWARE.
*/ */
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
/** /**
@ -61,10 +60,11 @@ public class Property {
public static Properties toProperties(JSONObject jo) throws JSONException { public static Properties toProperties(JSONObject jo) throws JSONException {
Properties properties = new Properties(); Properties properties = new Properties();
if (jo != null) { if (jo != null) {
for (final Entry<String, ?> entry : jo.entrySet()) { // Don't use the new entrySet API to maintain Android support
Object value = entry.getValue(); for (final String key : jo.keySet()) {
Object value = jo.opt(key);
if (!JSONObject.NULL.equals(value)) { if (!JSONObject.NULL.equals(value)) {
properties.put(entry.getKey(), value.toString()); properties.put(key, value.toString());
} }
} }
} }

View file

@ -25,7 +25,6 @@ SOFTWARE.
*/ */
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry;
/** /**
* This provides static methods to convert an XML text into a JSONObject, and to * This provides static methods to convert an XML text into a JSONObject, and to
@ -430,11 +429,49 @@ public class XML {
* @return JSON value of this string or the string * @return JSON value of this string or the string
*/ */
public static Object stringToValue(String string) { public static Object stringToValue(String string) {
Object ret = JSONObject.stringToValue(string); if (string.equals("")) {
if(ret instanceof String){ return string;
return unescape((String)ret);
} }
return ret; if (string.equalsIgnoreCase("true")) {
return Boolean.TRUE;
}
if (string.equalsIgnoreCase("false")) {
return Boolean.FALSE;
}
if (string.equalsIgnoreCase("null")) {
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 {
// if we want full Big Number support this block can be replaced with:
// return stringToNumber(string);
if (string.indexOf('.') > -1 || string.indexOf('e') > -1
|| string.indexOf('E') > -1 || "-0".equals(string)) {
Double d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) {
return d;
}
} else {
Long myLong = Long.valueOf(string);
if (string.equals(myLong.toString())) {
if (myLong.longValue() == myLong.intValue()) {
return Integer.valueOf(myLong.intValue());
}
return myLong;
}
}
} catch (Exception ignore) {
}
}
return unescape(string);
} }
/** /**
@ -482,9 +519,12 @@ public class XML {
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
JSONObject jo = new JSONObject(); JSONObject jo = new JSONObject();
XMLTokener x = new XMLTokener(string); XMLTokener x = new XMLTokener(string);
while (x.more() && x.skipPast("<")) { while (x.more()) {
x.skipPast("<");
if(x.more()) {
parse(x, jo, null, keepStrings); parse(x, jo, null, keepStrings);
} }
}
return jo; return jo;
} }
/** /**
@ -526,10 +566,10 @@ public class XML {
} }
// Loop thru the keys. // Loop thru the keys.
// don't use the new entrySet accessor to maintain Android Support
jo = (JSONObject) object; jo = (JSONObject) object;
for (final Entry<String, ?> entry : jo.entrySet()) { for (final String key : jo.keySet()) {
final String key = entry.getKey(); Object value = jo.opt(key);
Object value = entry.getValue();
if (value == null) { if (value == null) {
value = ""; value = "";
} else if (value.getClass().isArray()) { } else if (value.getClass().isArray()) {
@ -540,13 +580,14 @@ public class XML {
if ("content".equals(key)) { if ("content".equals(key)) {
if (value instanceof JSONArray) { if (value instanceof JSONArray) {
ja = (JSONArray) value; ja = (JSONArray) value;
int i = 0; int jaLength = ja.length();
for (Object val : ja) { // don't use the new iterator API to maintain support for Android
for (int i = 0; i < jaLength; i++) {
if (i > 0) { if (i > 0) {
sb.append('\n'); sb.append('\n');
} }
Object val = ja.opt(i);
sb.append(escape(val.toString())); sb.append(escape(val.toString()));
i++;
} }
} else { } else {
sb.append(escape(value.toString())); sb.append(escape(value.toString()));
@ -556,7 +597,10 @@ public class XML {
} else if (value instanceof JSONArray) { } else if (value instanceof JSONArray) {
ja = (JSONArray) value; ja = (JSONArray) value;
for (Object val : ja) { 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) { if (val instanceof JSONArray) {
sb.append('<'); sb.append('<');
sb.append(key); sb.append(key);
@ -597,7 +641,10 @@ public class XML {
} else { } else {
ja = (JSONArray) object; ja = (JSONArray) object;
} }
for (Object val : ja) { 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 // XML does not have good support for arrays. If an array
// appears in a place where XML is lacking, synthesize an // appears in a place where XML is lacking, synthesize an
// <array> element. // <array> element.

View file

@ -297,9 +297,8 @@ public class XMLTokener extends JSONTokener {
* Skip characters until past the requested string. * 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. * 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. * @param to A string to skip past.
* @throws JSONException
*/ */
public boolean skipPast(String to) throws JSONException { public void skipPast(String to) {
boolean b; boolean b;
char c; char c;
int i; int i;
@ -316,7 +315,7 @@ public class XMLTokener extends JSONTokener {
for (i = 0; i < length; i += 1) { for (i = 0; i < length; i += 1) {
c = next(); c = next();
if (c == 0) { if (c == 0) {
return false; return;
} }
circle[i] = c; circle[i] = c;
} }
@ -343,14 +342,14 @@ public class XMLTokener extends JSONTokener {
/* If we exit the loop with b intact, then victory is ours. */ /* If we exit the loop with b intact, then victory is ours. */
if (b) { if (b) {
return true; return;
} }
/* Get the next character. If there isn't one, then defeat is ours. */ /* Get the next character. If there isn't one, then defeat is ours. */
c = next(); c = next();
if (c == 0) { if (c == 0) {
return false; return;
} }
/* /*
* Shove the character in the circle buffer and advance the * Shove the character in the circle buffer and advance the