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

Merge pull request #350 from johnjaylward/AndroidSupport

Updates for supporting the Android API
This commit is contained in:
Sean Leary 2017-10-30 11:33:10 -05:00 committed by GitHub
commit 722003d479
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 207 additions and 101 deletions

View file

@ -1,7 +1,5 @@
package org.json;
import java.util.Map.Entry;
/*
Copyright (c) 2002 JSON.org
@ -24,7 +22,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
*/
/**
* Convert a web browser cookie list string to a JSONObject and back.
@ -69,10 +67,10 @@ public class CookieList {
*/
public static String toString(JSONObject jo) throws JSONException {
boolean b = false;
StringBuilder sb = new StringBuilder();
for (final Entry<String,?> entry : jo.entrySet()) {
final String key = entry.getKey();
final Object value = entry.getValue();
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) {
sb.append(';');

View file

@ -25,7 +25,6 @@ SOFTWARE.
*/
import java.util.Locale;
import java.util.Map.Entry;
/**
* 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.");
}
sb.append(CRLF);
for (final Entry<String,?> entry : jo.entrySet()) {
final String key = entry.getKey();
// Don't use the new entrySet API to maintain Android support
for (final String key : jo.keySet()) {
String value = jo.optString(key);
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())) {
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
sb.append(key);
sb.append(": ");
sb.append(jo.optString(key));

View file

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

View file

@ -1950,6 +1950,8 @@ public class JSONObject {
* A String.
* @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) {
if (string.equals("")) {
return string;
@ -2120,55 +2122,11 @@ public class JSONObject {
* 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 = 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());
// moves the implementation to JSONWriter as:
// 1. It makes more sense to be part of the writer class
// 2. For Android support this method is not available. By implementing it in the Writer
// Android users can use the writer with the built in Android JSONObject implementation.
return JSONWriter.valueToString(value);
}
/**

View file

@ -5,7 +5,9 @@ import static java.lang.String.format;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
Copyright (c) 2002 JSON.org
@ -181,7 +183,7 @@ public class JSONPointer {
* @return the result of the 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()) {
return document;
}
@ -205,10 +207,9 @@ public class JSONPointer {
* @param current the JSONArray to be evaluated
* @param indexToken the array index in string form
* @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) {
private Object readByIndexToken(Object current, String indexToken) throws JSONPointerException {
try {
int index = Integer.parseInt(indexToken);
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,
currentArr.length()));
}
try {
return currentArr.get(index);
} catch (JSONException e) {
throw new JSONPointerException("Error reading value at index position " + index, e);
}
} catch (NumberFormatException e) {
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
}

View file

@ -1,6 +1,9 @@
package org.json;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Map;
/*
Copyright (c) 2006 JSON.org
@ -117,6 +120,9 @@ public class JSONWriter {
}
this.writer.append(string);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
if (this.mode == 'o') {
@ -164,6 +170,9 @@ public class JSONWriter {
try {
this.writer.append(c);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
this.comma = true;
@ -204,7 +213,12 @@ public class JSONWriter {
}
if (this.mode == 'k') {
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) {
this.writer.append(',');
}
@ -214,6 +228,9 @@ public class JSONWriter {
this.mode = 'o';
return this;
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
}
@ -280,6 +297,81 @@ public class JSONWriter {
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
@ -321,6 +413,6 @@ public class JSONWriter {
* @throws JSONException If the value is out of sequence.
*/
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.Map.Entry;
import java.util.Properties;
/**
@ -41,7 +40,9 @@ public class Property {
* @throws JSONException
*/
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
JSONObject jo = new JSONObject(properties == null ? 0 : properties.size());
// can't use the new constructor for Android support
// JSONObject jo = new JSONObject(properties == null ? 0 : properties.size());
JSONObject jo = new JSONObject();
if (properties != null && !properties.isEmpty()) {
Enumeration<?> enumProperties = properties.propertyNames();
while(enumProperties.hasMoreElements()) {
@ -61,10 +62,11 @@ public class Property {
public static Properties toProperties(JSONObject jo) throws JSONException {
Properties properties = new Properties();
if (jo != null) {
for (final Entry<String, ?> entry : jo.entrySet()) {
Object value = entry.getValue();
// Don't use the new entrySet API to maintain Android support
for (final String key : jo.keySet()) {
Object value = jo.opt(key);
if (!JSONObject.NULL.equals(value)) {
properties.put(entry.getKey(), value.toString());
properties.put(key, value.toString());
}
}
}

View file

@ -25,7 +25,6 @@ SOFTWARE.
*/
import java.util.Iterator;
import java.util.Map.Entry;
/**
* This provides static methods to convert an XML text into a JSONObject, and to
@ -399,14 +398,56 @@ public class XML {
}
/**
* This method is the same as {@link JSONObject#stringToValue(String)}
* except that this also tries to unescape String values.
* This method is the same as {@link JSONObject#stringToValue(String)}.
*
* @param string String to convert
* @return JSON value of this string or the string
*/
// To maintain compatibility with the Android API, this method is a direct copy of
// the one in JSONObject. Changes made here should be reflected there.
public static Object stringToValue(String string) {
return JSONObject.stringToValue(string);
if (string.equals("")) {
return string;
}
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 string;
}
/**
@ -454,9 +495,12 @@ public class XML {
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
JSONObject jo = new JSONObject();
XMLTokener x = new XMLTokener(string);
while (x.more() && x.skipPast("<")) {
while (x.more()) {
x.skipPast("<");
if(x.more()) {
parse(x, jo, null, keepStrings);
}
}
return jo;
}
/**
@ -498,10 +542,10 @@ public class XML {
}
// Loop thru the keys.
// don't use the new entrySet accessor to maintain Android Support
jo = (JSONObject) object;
for (final Entry<String, ?> entry : jo.entrySet()) {
final String key = entry.getKey();
Object value = entry.getValue();
for (final String key : jo.keySet()) {
Object value = jo.opt(key);
if (value == null) {
value = "";
} else if (value.getClass().isArray()) {
@ -512,13 +556,14 @@ public class XML {
if ("content".equals(key)) {
if (value instanceof JSONArray) {
ja = (JSONArray) value;
int i = 0;
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++) {
if (i > 0) {
sb.append('\n');
}
Object val = ja.opt(i);
sb.append(escape(val.toString()));
i++;
}
} else {
sb.append(escape(value.toString()));
@ -528,7 +573,10 @@ public class XML {
} else if (value instanceof JSONArray) {
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) {
sb.append('<');
sb.append(key);
@ -569,7 +617,10 @@ public class XML {
} else {
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
// appears in a place where XML is lacking, synthesize an
// <array> element.

View file

@ -326,9 +326,11 @@ public class XMLTokener extends JSONTokener {
* Skip characters until past the requested string.
* If it is not found, we are left at the end of the source with a result of false.
* @param to A string to skip past.
* @throws JSONException
*/
public boolean skipPast(String to) throws JSONException {
// The Android implementation of JSONTokener has a public method of public void skipPast(String to)
// even though ours does not have that method, to have API compatibility, our method in the subclass
// should match.
public void skipPast(String to) {
boolean b;
char c;
int i;
@ -345,7 +347,7 @@ public class XMLTokener extends JSONTokener {
for (i = 0; i < length; i += 1) {
c = next();
if (c == 0) {
return false;
return;
}
circle[i] = c;
}
@ -372,14 +374,14 @@ public class XMLTokener extends JSONTokener {
/* If we exit the loop with b intact, then victory is ours. */
if (b) {
return true;
return;
}
/* Get the next character. If there isn't one, then defeat is ours. */
c = next();
if (c == 0) {
return false;
return;
}
/*
* Shove the character in the circle buffer and advance the