24 Commits

Author SHA1 Message Date
Sean Leary
61cdfefc36 Update README.md 2018-01-30 19:46:24 -06:00
Sean Leary
fbad2d0017 Merge pull request #392 from philippgille/patch-1
Remove wrong apostrophe
2018-01-20 03:39:07 -06:00
Philipp Gillé
15719886f7 Remove wrong apostrophe 2018-01-17 18:41:48 +01:00
Sean Leary
ca45b02ffc Merge pull request #381 from fleipold/maven-badge
Adding maven badge to readme
2018-01-14 10:18:46 -06:00
Felix Leipold
b6efbabc32 Making links markdown links 2017-11-17 12:47:49 +01:00
Felix Leipold
9eb8c27724 Marking up class and method names as inline code 2017-11-17 12:33:50 +01:00
Felix Leipold
195963357c Make file names bold 2017-11-17 12:24:17 +01:00
Felix Leipold
28efdb4860 Moving Badge below title 2017-11-17 12:24:03 +01:00
Felix Leipold
c88653ca2e History with fixed font 2017-11-14 17:23:53 +01:00
Felix Leipold
b3068d9fe4 Marking file and class names with single quotes 2017-11-14 17:23:52 +01:00
Felix Leipold
dba4afd0cf Adding maven repo badge 2017-11-14 17:23:36 +01:00
Felix Leipold
26160e1619 Remove trailing whitespace 2017-11-14 17:23:36 +01:00
Felix Leipold
b7e2eee4d6 Renaming README to README.md 2017-11-14 17:23:36 +01:00
Sean Leary
28e09dc493 Merge pull request #380 from johnjaylward/FixFalsePositiveSimilar
Fix for false positives in similar functions
2017-11-11 16:12:06 -06:00
John J. Aylward
4a4b2db8c1 fix for issue #379 2017-11-06 10:28:28 -05:00
Sean Leary
f16682bf44 Merge pull request #375 from johnjaylward/FixExceptionWrapping
fixes wrapped exceptions
2017-11-02 21:42:29 -05:00
John J. Aylward
18952b5ac0 fixes wrapped exceptions 2017-11-02 22:32:24 -04:00
Sean Leary
d2a66a4287 Merge pull request #373 from johnjaylward/UnclosedJSONArray
Fixes Unclosed json array stack overflow
2017-11-02 20:02:26 -05:00
Sean Leary
722003d479 Merge pull request #350 from johnjaylward/AndroidSupport
Updates for supporting the Android API
2017-10-30 11:33:10 -05:00
John J. Aylward
ed8745cd63 fixes #372.
Corrects behavior of unclosed arrays
2017-10-30 08:18:59 -04:00
John J. Aylward
057e0c75ca Merge remote-tracking branch 'origin/master' into AndroidSupport 2017-10-27 13:28:20 -04:00
John J. Aylward
3997a90d58 update constructor call to match Android implementation 2017-07-07 12:24:27 -04:00
John J. Aylward
1736a60ffe adds comment for the API change 2017-07-07 12:17:45 -04:00
John J. Aylward
e8b1b66888 Updates for supporting the Android API 2017-07-07 12:17:39 -04:00
12 changed files with 269 additions and 138 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# ignore eclipse project files
.project
.classpath

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
@@ -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, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
/** /**
* Convert a web browser cookie list string to a JSONObject and back. * Convert a web browser cookie list string to a JSONObject and back.
@@ -69,17 +67,17 @@ 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(';');
} }
sb.append(Cookie.escape(key)); sb.append(Cookie.escape(key));
sb.append("="); sb.append("=");
sb.append(Cookie.escape(value.toString())); sb.append(Cookie.escape(value.toString()));
b = true; b = true;
} }
} }

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

@@ -107,7 +107,13 @@ public class JSONArray implements Iterable<Object> {
if (x.nextClean() != '[') { if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['"); throw x.syntaxError("A JSONArray text must start with '['");
} }
if (x.nextClean() != ']') {
char nextChar = x.nextClean();
if (nextChar == 0) {
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar != ']') {
x.back(); x.back();
for (;;) { for (;;) {
if (x.nextClean() == ',') { if (x.nextClean() == ',') {
@@ -118,8 +124,16 @@ public class JSONArray implements Iterable<Object> {
this.myArrayList.add(x.nextValue()); this.myArrayList.add(x.nextValue());
} }
switch (x.nextClean()) { switch (x.nextClean()) {
case 0:
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
case ',': case ',':
if (x.nextClean() == ']') { nextChar = x.nextClean();
if (nextChar == 0) {
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar == ']') {
return; return;
} }
x.back(); x.back();
@@ -1275,7 +1289,7 @@ public class JSONArray implements Iterable<Object> {
Object valueThis = this.myArrayList.get(i); Object valueThis = this.myArrayList.get(i);
Object valueOther = ((JSONArray)other).myArrayList.get(i); Object valueOther = ((JSONArray)other).myArrayList.get(i);
if(valueThis == valueOther) { if(valueThis == valueOther) {
return true; continue;
} }
if(valueThis == null) { if(valueThis == null) {
return false; return false;

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

@@ -1844,7 +1844,7 @@ public class JSONObject {
Object valueThis = entry.getValue(); Object valueThis = entry.getValue();
Object valueOther = ((JSONObject)other).get(name); Object valueOther = ((JSONObject)other).get(name);
if(valueThis == valueOther) { if(valueThis == valueOther) {
return true; continue;
} }
if(valueThis == null) { if(valueThis == null) {
return false; return false;
@@ -1950,6 +1950,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;
@@ -2120,55 +2122,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());
} }
/** /**
@@ -2254,7 +2212,7 @@ public class JSONObject {
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary // not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
final String numberAsString = numberToString((Number) value); final String numberAsString = numberToString((Number) value);
try { try {
// Use the BigDecimal constructor for it's parser to validate the format. // Use the BigDecimal constructor for its parser to validate the format.
@SuppressWarnings("unused") @SuppressWarnings("unused")
BigDecimal testNum = new BigDecimal(numberAsString); BigDecimal testNum = new BigDecimal(numberAsString);
// Close enough to a JSON number that we will use it unquoted // Close enough to a JSON number that we will use it unquoted

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()));
} }
return currentArr.get(index); try {
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;
/** /**
@@ -41,7 +40,9 @@ public class Property {
* @throws JSONException * @throws JSONException
*/ */
public static JSONObject toJSONObject(java.util.Properties properties) 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()) { if (properties != null && !properties.isEmpty()) {
Enumeration<?> enumProperties = properties.propertyNames(); Enumeration<?> enumProperties = properties.propertyNames();
while(enumProperties.hasMoreElements()) { while(enumProperties.hasMoreElements()) {
@@ -61,10 +62,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

@@ -1,4 +1,7 @@
JSON in Java [package org.json] JSON in Java [package org.json]
===============================
[![Maven Central](https://img.shields.io/maven-central/v/org.json/json.svg)](https://mvnrepository.com/artifact/org.json/json)
JSON is a light-weight, language independent, data interchange format. JSON is a light-weight, language independent, data interchange format.
See http://www.JSON.org/ See http://www.JSON.org/
@@ -18,64 +21,63 @@ package.
The package compiles on Java 1.6-1.8. The package compiles on Java 1.6-1.8.
JSONObject.java: The JSONObject can parse text from a String or a JSONTokener **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 to produce a map-like object. The object provides methods for manipulating its
contents, and for producing a JSON compliant object serialization. contents, and for producing a JSON compliant object serialization.
JSONArray.java: The JSONArray 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 to produce a vector-like object. The object provides methods for manipulating
its contents, and for producing a JSON compliant array serialization. its contents, and for producing a JSON compliant array serialization.
JSONTokener.java: The JSONTokener breaks a text into a sequence of individual **JSONTokener.java**: The `JSONTokener` breaks a text into a sequence of individual
tokens. It can be constructed from a String, Reader, or InputStream. tokens. It can be constructed from a `String`, `Reader`, or `InputStream`.
JSONException.java: The JSONException is the standard exception type thrown **JSONException.java**: The `JSONException` is the standard exception type thrown
by this package. by this package.
JSONPointer.java: Implementation of **JSONPointer.java**: Implementation of
[JSON Pointer (RFC 6901)](https://tools.ietf.org/html/rfc6901). Supports [JSON Pointer (RFC 6901)](https://tools.ietf.org/html/rfc6901). Supports
JSON Pointers both in the form of string representation and URI fragment JSON Pointers both in the form of string representation and URI fragment
representation. representation.
JSONString.java: The JSONString interface requires a toJSONString method, **JSONString.java**: The `JSONString` interface requires a `toJSONString` method,
allowing an object to provide its own serialization. allowing an object to provide its own serialization.
JSONStringer.java: The JSONStringer provides a convenient facility for **JSONStringer.java**: The `JSONStringer` provides a convenient facility for
building JSON strings. building JSON strings.
JSONWriter.java: The JSONWriter provides a convenient facility for building **JSONWriter.java**: The `JSONWriter` provides a convenient facility for building
JSON text through a writer. JSON text through a writer.
CDL.java: CDL provides support for converting between JSON and comma **CDL.java**: `CDL` provides support for converting between JSON and comma
delimited lists. delimited lists.
Cookie.java: Cookie provides support for converting between JSON and cookies. **Cookie.java**: `Cookie` provides support for converting between JSON and cookies.
CookieList.java: CookieList provides support for converting between JSON and **CookieList.java**: `CookieList` provides support for converting between JSON and
cookie lists. cookie lists.
HTTP.java: HTTP provides support for converting between JSON and HTTP headers. **HTTP.java**: `HTTP` provides support for converting between JSON and HTTP headers.
HTTPTokener.java: HTTPTokener extends JSONTokener for parsing HTTP headers. **HTTPTokener.java**: `HTTPTokener` extends `JSONTokener` for parsing HTTP headers.
XML.java: XML provides support for converting between JSON and XML. **XML.java**: `XML` provides support for converting between JSON and XML.
JSONML.java: JSONML provides support for converting between JSONML and XML. **JSONML.java**: `JSONML` provides support for converting between JSONML and XML.
XMLTokener.java: XMLTokener extends JSONTokener for parsing XML text. **XMLTokener.java**: `XMLTokener` extends `JSONTokener` for parsing XML text.
Unit tests are maintained in a separate project. Contributing developers can test Unit tests are maintained in a separate project. Contributing developers can test
JSON-java pull requests with the code in this project: JSON-java pull requests with the code in this project:
https://github.com/stleary/JSON-Java-unit-test https://github.com/stleary/JSON-Java-unit-test
Numeric types in this package comply with ECMA-404: The JSON Data Interchange Format Numeric types in this package comply with
(http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) and [ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) and
RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159#section-6).
(https://tools.ietf.org/html/rfc7159#section-6). This package fully supports `Integer`, `Long`, and `Double` Java types. Partial support
This package fully supports Integer, Long, and Double Java types. Partial support for `BigInteger` and `BigDecimal` values in `JSONObject` and `JSONArray` objects is provided
for BigInteger and BigDecimal values in JSONObject and JSONArray objects is provided in the form of `get()`, `opt()`, and `put()` API methods.
in the form of get(), opt(), and put() API methods.
Although 1.6 compatibility is currently supported, it is not a project goal and may be Although 1.6 compatibility is currently supported, it is not a project goal and may be
removed in some future release. removed in some future release.
@@ -89,16 +91,20 @@ invalid number formats (1.2e6.3) will cause errors as such documents can not be
reliably. reliably.
Release history: Release history:
~~~
20180130 Recent commits
20171018 Checkpoint for recent commits. 20171018 Checkpoint for recent commits.
20170516 Roll up recent commits. 20170516 Roll up recent commits.
20160810 Revert code that was breaking opt*() methods. 20160810 Revert code that was breaking opt*() methods.
20160807 This release contains a bug in the JSONObject.opt*() and JSONArray.opt*() methods, 20160807 This release contains a bug in the JSONObject.opt*() and JSONArray.opt*() methods,
it is not recommended for use. it is not recommended for use.
Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(), Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(),
RFC4180 compatibility, JSONPointer, some exception fixes, optional XML type conversion. RFC4180 compatibility, JSONPointer, some exception fixes, optional XML type conversion.
Contains the latest code as of 7 Aug, 2016 Contains the latest code as of 7 Aug, 2016
20160212 Java 1.6 compatibility, OSGi bundle. Contains the latest code as of 12 Feb, 2016. 20160212 Java 1.6 compatibility, OSGi bundle. Contains the latest code as of 12 Feb, 2016.
@@ -106,9 +112,11 @@ Contains the latest code as of 7 Aug, 2016
20151123 JSONObject and JSONArray initialization with generics. Contains the 20151123 JSONObject and JSONArray initialization with generics. Contains the
latest code as of 23 Nov, 2015. latest code as of 23 Nov, 2015.
20150729 Checkpoint for Maven central repository release. Contains the latest code 20150729 Checkpoint for Maven central repository release. Contains the latest code
as of 29 July, 2015. as of 29 July, 2015.
~~~
JSON-java releases can be found by searching the Maven repository for groupId "org.json"
and artifactId "json". For example: JSON-java releases can be found by searching the Maven repository for groupId "org.json"
and artifactId "json". For example:
https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.json%22%20AND%20a%3A%22json%22 https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.json%22%20AND%20a%3A%22json%22

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
@@ -399,14 +398,56 @@ public class XML {
} }
/** /**
* This method is the same as {@link JSONObject#stringToValue(String)} * This method is the same as {@link JSONObject#stringToValue(String)}.
* except that this also tries to unescape String values.
* *
* @param string String to convert * @param string String to convert
* @return JSON value of this string or the string * @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) { 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,8 +495,11 @@ 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()) {
parse(x, jo, null, keepStrings); x.skipPast("<");
if(x.more()) {
parse(x, jo, null, keepStrings);
}
} }
return jo; return jo;
} }
@@ -498,10 +542,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()) {
@@ -512,13 +556,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()));
@@ -528,7 +573,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);
@@ -569,7 +617,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

@@ -326,9 +326,11 @@ 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 { // 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; boolean b;
char c; char c;
int i; int i;
@@ -345,7 +347,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;
} }
@@ -372,14 +374,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