97 Commits

Author SHA1 Message Date
Sean Leary
8e079599c4 Update README 2016-08-07 15:19:44 -05:00
Sean Leary
3080b8beeb Merge pull request #253 from johnjaylward/OptionalTypeConversion
Optional type conversion for XML reading
2016-07-31 21:09:07 -05:00
Sean Leary
2c228ecf1a Merge pull request #249 from Simulant87/master
reduces the use of unnecessary exceptions
2016-07-26 23:04:49 -05:00
Nils Faupel
3890bfae52 reduce the use of unnecessary exceptions 2016-07-19 19:59:30 +02:00
Nils Faupel
abf2963bbe Revert "reduces the use of unnecessary exceptions"
This reverts commit 7627d40d10.
2016-07-19 19:00:42 +02:00
John J. Aylward
09d37e59b8 Cleans up the JSONML changes and adds similar changes to the XML class 2016-07-18 14:42:21 -04:00
John J. Aylward
93704371bb Updates to the Javadoc for exceptions 2016-07-18 14:12:06 -04:00
Jakob Stemberger
42e0944708 Brings in changes from PR #70 to be updated to HEAD 2016-07-18 13:45:31 -04:00
Simulant
7627d40d10 reduces the use of unnecessary exceptions 2016-07-08 22:17:05 +02:00
Sean Leary
04181fb6e2 Merge pull request #246 from johnjaylward/LicenseFile
Add License file
2016-07-02 13:20:54 -05:00
Sean Leary
239e0b7070 Merge pull request #242 from johnjaylward/issue240
Fixes Issue #240
2016-07-02 13:20:21 -05:00
johnjaylward
a8a71898a3 Create LICENSE 2016-06-22 14:49:52 -04:00
johnjaylward
86e8f7b313 Update README
fixes typo
2016-06-17 16:39:11 -04:00
John J. Aylward
42791ab12d Updates README to note that the parser does allow some invalid JSON 2016-06-16 13:01:22 -04:00
johnjaylward
b3abaa5b4c Merge pull request #1 from stleary/master
update from origin
2016-06-16 11:43:05 -04:00
Sean Leary
eb569b58fc Merge pull request #236 from madsager/master
Make nextString throw a JSONException instead of a NumberFormatExcept…
2016-06-07 21:29:02 -05:00
Mads Ager
16a86d73df Pass in the throwable that caused the error. 2016-06-02 16:11:15 +02:00
Mads Ager
dfa651e777 Make nextString throw a JSONException instead of a NumberFormatException for malformed input. 2016-06-02 15:56:48 +02:00
Sean Leary
612dafc750 Update JSONObject.java 2016-05-20 21:10:17 -05:00
Sean Leary
808320801a Update JSONArray.java
Update version timestamp
2016-05-20 21:09:53 -05:00
Sean Leary
b2bde1f468 Merge pull request #234 from erosb/master
fixing stleary/JSON-Java#233
2016-05-20 21:03:06 -05:00
Bence Erős
56be31e7a8 fixing stleary/JSON-Java#233 2016-05-16 14:53:34 +02:00
stleary
9a81b40334 added some JavaDocs 2016-05-14 11:09:51 -05:00
stleary
4a458a9f1c add timestamps to recent commits, javadocs for JSONObject, JSONArray queryFrom() methods 2016-05-14 09:22:18 -05:00
Sean Leary
8a72509e6e Merge pull request #222 from erosb/master
JSON Pointer implementation
2016-05-13 22:46:52 -05:00
Bence Erős
c044eb14dd added copying to JSONPointer constructor 2016-05-05 15:59:43 +02:00
Bence Erős
5ae6a66e38 added javadoc & null check in Builder#append(String) 2016-05-03 23:41:51 +02:00
Bence Erős
d833c2d8de added builder class for JSONPointer, and implemented toString() and toURIFragment() 2016-05-03 23:18:05 +02:00
Sean Leary
f21ffbe189 Update CDL.java
Date of last change.
2016-05-02 22:12:29 -05:00
Sean Leary
cad23423ab Update JSONObject.java
Forgot to update date of last change
2016-05-02 22:11:20 -05:00
Sean Leary
ebf08f5651 Merge pull request #226 from stleary/restore-1.6-compatibility
fix to compile with 1.6.0_45
2016-05-01 22:59:29 -05:00
Sean Leary
f239dc75ad Merge pull request #219 from captainIowa/master
Added CSV change to CDL.java
2016-05-01 22:55:13 -05:00
stleary
1ca8933a8f fix to compile with 1.6.0_45 2016-04-28 22:12:16 -05:00
Bence Erős
cbb1546c53 README improvements for stleary/JSON-Java#218 2016-04-28 16:45:17 +02:00
Bence Erős
c1a789a70c adding missing license headers 2016-04-27 00:11:47 +02:00
Bence Erős
bff352791c removed @author tag from JSONPointerException 2016-04-27 00:10:45 +02:00
Bence Erős
5223aadd67 added some javadoc to JSONPointer 2016-04-27 00:10:06 +02:00
Bence Erős
45bd72c15d added JSONObject#query() and JSONPointer#query() methods 2016-04-26 23:48:14 +02:00
Bence Erős
792c6f6a9c improved failure handling 2016-04-26 23:32:15 +02:00
Bence Erős
5bee7e3b45 escape handling improvements & URL fragment notation handling 2016-04-26 23:00:16 +02:00
Bence Erős
612e41950c initial implementation of JSONPointer 2016-04-17 23:21:38 +02:00
Brian Russell
86cbfbc864 Added CSV change to CDL.java 2016-04-12 14:13:15 -04:00
Sean Leary
25a87975be Update date of merge. 2016-03-05 15:20:20 -06:00
Sean Leary
2f3af56535 Update date of merge. 2016-03-05 15:19:45 -06:00
Sean Leary
26477f4e76 Merge pull request #203 from joeferner/to-java
Adds JSONArray toList method and JSONObject toMap method
2016-03-05 15:18:38 -06:00
Joe Ferner
f024b52108 Adds JSONArray toList method and JSONObject toMap method 2016-02-27 11:20:25 -05:00
Sean Leary
2657915293 Update README
Include some text about 1.6 compatibility and add the latest release information.
2016-02-13 22:26:45 -06:00
Sean Leary
07a0f60b6e Merge pull request #195 from publishing-systems/master
Java 1.6 compatibility.
2016-02-12 18:10:13 -06:00
skreutzer
60349ece54 Java 1.6 compatibility. 2016-02-08 23:30:27 -05:00
Sean Leary
ba2585fe6c Version date 2016-01-30 15:45:11 -06:00
Sean Leary
93c79ca566 Version date 2016-01-30 15:44:41 -06:00
Sean Leary
62486fdea4 Version date 2016-01-30 15:44:08 -06:00
Sean Leary
97f1b2744f Merge pull request #188 from johnjaylward/FixNegativeZero
Fix negative zero
2016-01-30 15:42:34 -06:00
John J. Aylward
c2b3f2bdb1 adds back in the XML.stringToValue method, but deprecates it. 2016-01-27 15:21:11 -05:00
John J. Aylward
3007fc8ebe Removes custom XML stringToValue method in favor of keeping a consistent
implementation in JSONObject
2016-01-27 15:03:19 -05:00
John J. Aylward
39b1c0cb66 fixes error in -0 check 2016-01-27 10:45:23 -05:00
John J. Aylward
07b2d65e30 Fixes #187 -0 now returns as a double. 2016-01-27 10:39:31 -05:00
John J. Aylward
5b67330b71 Merge branch 'master' of https://github.com/douglascrockford/JSON-java 2016-01-27 09:53:03 -05:00
Sean Leary
9950350f12 Merge pull request #186 from douglascrockford/update-readme-with-number-info
Update README with number information
2016-01-03 14:52:50 -06:00
Sean Leary
2b2fac3eb1 Broke up some overly long lines. 2016-01-01 16:17:30 -06:00
Sean Leary
e2a0bb16a2 Update README with number information
See https://github.com/douglascrockford/JSON-java/issues/162
2016-01-01 14:11:02 -06:00
Sean Leary
a971736f5b Update version string for https://github.com/douglascrockford/JSON-java/pull/170 2016-01-01 13:52:12 -06:00
Sean Leary
757fd566ab Merge pull request #170 from johnjaylward/HandleArraysConsistently
Handle arrays consistently
2016-01-01 13:44:57 -06:00
Sean Leary
e6f5047742 Merge pull request #185 from douglascrockford/write-with-indent-params
change to public: write(writer, indentfactor, indent)
2015-12-30 15:06:07 -06:00
stleary
8688494876 change to public, write(writer, indentfactor, indent) 2015-12-23 19:53:30 -06:00
John J. Aylward
48302592cf Merge branch 'master' of https://github.com/douglascrockford/JSON-java 2015-12-09 10:07:36 -05:00
Sean Leary
03dd662e72 Merge pull request #180 from netheril96/my
Remove executable bit
2015-12-09 01:08:47 -06:00
Siyuan Ren
23cf659730 Remove executable permission bit from file mode 2015-12-09 09:50:59 +08:00
John J. Aylward
ec8f649467 Merge branch 'master' of https://github.com/douglascrockford/JSON-java 2015-12-08 09:27:54 -05:00
Sean Leary
39e3ccc671 Update version
Update version after merge of https://github.com/douglascrockford/JSON-java/pull/179
2015-12-05 20:14:15 -06:00
Sean Leary
2ec538f420 Merge pull request #179 from andrew-fletcher/UpdateJavaDocForJSONOBject
Remove throws JSONException JavaDoc from 2 methods that do not throw this exception.
2015-12-05 20:11:40 -06:00
Andrew Fletcher
cadba9400c Update JavaDoc for JSONObject Constructors
Two JSONObject constructors incorrectly specify a @throws JSONException
tag in the JavaDoc for those constructors. Remove the relevant JavaDoc.
2015-12-02 10:49:54 -08:00
Sean Leary
44275e3b3c Merge pull request #175 from douglascrockford/release-20151123
Update readme for 20151123 release
2015-11-24 01:53:19 -06:00
stleary
5f2e77f9dd Update readme with proposed release information 2015-11-21 11:50:31 -06:00
Sean Leary
a109f581c8 Update JSONArray.java
Update version for https://github.com/douglascrockford/JSON-java/pull/153
2015-10-29 18:25:27 -05:00
Sean Leary
33ae025e78 Update JSONObject.java
Update version for https://github.com/douglascrockford/JSON-java/pull/153
2015-10-29 18:24:46 -05:00
Sean Leary
564ad2c2fb Merge pull request #153 from treyerl/master
JSONObject and JSONArray initialization for Map<?,?> and Collection<?>
2015-10-29 18:07:43 -05:00
Sean Leary
dfd19116d3 Merge pull request #168 from douglascrockford/readme-maven-info
Include latest Maven release information
2015-10-29 18:04:31 -05:00
John J. Aylward
105426b53f Formatting 2015-10-26 18:35:40 -04:00
John J. Aylward
7886c96204 Changes JSONArray for loops to use the new iterators. 2015-10-26 18:30:41 -04:00
John J. Aylward
91c6f09be8 Modifies XML output to be handled the same for a native java array as well as a JSONArray. 2015-10-26 18:17:37 -04:00
stleary
a07d391eae Include latest Maven release information 2015-10-25 11:05:16 -05:00
Sean Leary
e7f4eb5f67 Set version date to match commit date, convert tabs to spaces. 2015-10-18 11:05:29 -05:00
Sean Leary
b0a9507add Merge pull request #159 from johnjaylward/FixExceptionInheritance
Properly overrides the Exception class.
2015-10-18 11:02:11 -05:00
Sean Leary
6757e04c0a Fix NullPointerException in XML.toString(object, tagName)
Setting version date to match commit date.
2015-10-18 10:23:43 -05:00
Sean Leary
09b6af4712 Merge pull request #160 from johnjaylward/FixXMLNPE
Fixes possible NullPointerException in XML.toString(object, tagName)
2015-10-18 10:21:36 -05:00
John Aylward
637c1fe2b9 updates file dates 2015-10-14 00:48:01 -04:00
John Aylward
1448163981 fixes file date 2015-10-14 00:41:38 -04:00
Lukas Treyer
5ddc515679 removed 6 unnecessary @SuppressWarnings("unchecked") annotations. 2015-10-12 23:52:14 +02:00
John J. Aylward
1b06a802cf makes params final 2015-10-12 14:54:30 -04:00
John J. Aylward
0e13241528 Expands javadoc 2015-10-12 14:53:03 -04:00
John J. Aylward
e239e1967a Allows a custom message to be passed with a cause. 2015-10-12 14:52:17 -04:00
John J. Aylward
ceba8e8c3d Fixes possible NPE 2015-10-12 14:25:18 -04:00
John J. Aylward
4e77383472 Properly overrides the Exception class. 2015-10-12 14:23:05 -04:00
Lukas Treyer
25b5aa7ef2 changed Map<String, ?> method parameters to Map<?,?>
changed Iterator to foreach loop in JSONArray ctor
JSONArray(Collection<?> collection) and JSONObject ctor
JSONObject(Map<?,?> map)
2015-10-11 12:21:12 +02:00
Lukas Treyer
409eb9f292 changed all method signatures containing collections and maps to accept
wildcard generic types, e.g. Collection<?> instead of
Collection<Object>. This was proposed by other pull requests (#111,
#112) already. Consider this commit as merge with #111 and #112.

JSONArray:
	- put(Collection<?> value) {...}
	- put(Map<String, ?> value) {...}
	- put(int index, Collection<?> value) throws JSONException {...}
	- put(int index, Map<String, ?> value) throws JSONException {...}

JSONObject:
	- put(String key, Collection<?> value) throws JSONException {...}
	- put(String key, Map<String, ?> value) throws JSONException {...}


Changed all code affected by new JSONObject and JSONArray constructors:
	
JSONObject:
	- valueToString(Object value) throws JSONException {
		- value instanceof Map
		- value instanceof Collection
	  }
	- wrap(Object object) {
		- value instanceof Map
		- value instanceof Collection
	  }
	- writeValue(Writer writer, Object value,
			 int indentFactor, int indent){
        - value instanceof Map
        - value instanceof Collection
      }
2015-10-11 11:20:08 +02:00
Lukas Treyer
0afd26623c JSONObject and JSONArray initialization:
JSONObject(Map<String, ?> map) allows to initialize the JSONObject with
a Map<String, String>

JSONArray(Collection<?> collection) allows to initialize a JSONArray
with a Collection<JSONObject>
2015-10-04 23:17:30 +02:00
19 changed files with 1071 additions and 329 deletions

7
CDL.java Executable file → Normal file
View File

@@ -41,7 +41,7 @@ SOFTWARE.
* The names for the elements in the JSONObjects can be taken from the names * The names for the elements in the JSONObjects can be taken from the names
* in the first row. * in the first row.
* @author JSON.org * @author JSON.org
* @version 2015-05-01 * @version 2016-05-01
*/ */
public class CDL { public class CDL {
@@ -69,8 +69,13 @@ public class CDL {
for (;;) { for (;;) {
c = x.next(); c = x.next();
if (c == q) { if (c == q) {
//Handle escaped double-quote
if(x.next() != '\"')
{
x.back();
break; break;
} }
}
if (c == 0 || c == '\n' || c == '\r') { if (c == 0 || c == '\n' || c == '\r') {
throw x.syntaxError("Missing close quote '" + q + "'."); throw x.syntaxError("Missing close quote '" + q + "'.");
} }

2
Cookie.java Executable file → Normal file
View File

@@ -28,7 +28,7 @@ SOFTWARE.
* Convert a web browser cookie specification to a JSONObject and back. * Convert a web browser cookie specification to a JSONObject and back.
* JSON and Cookies are both notations for name/value pairs. * JSON and Cookies are both notations for name/value pairs.
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class Cookie { public class Cookie {

2
CookieList.java Executable file → Normal file
View File

@@ -29,7 +29,7 @@ import java.util.Iterator;
/** /**
* Convert a web browser cookie list string to a JSONObject and back. * Convert a web browser cookie list string to a JSONObject and back.
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class CookieList { public class CookieList {

2
HTTP.java Executable file → Normal file
View File

@@ -29,7 +29,7 @@ import java.util.Iterator;
/** /**
* Convert an HTTP header to a JSONObject and back. * Convert an HTTP header to a JSONObject and back.
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class HTTP { public class HTTP {

2
HTTPTokener.java Executable file → Normal file
View File

@@ -28,7 +28,7 @@ SOFTWARE.
* The HTTPTokener extends the JSONTokener to provide additional methods * The HTTPTokener extends the JSONTokener to provide additional methods
* for the parsing of HTTP headers. * for the parsing of HTTP headers.
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class HTTPTokener extends JSONTokener { public class HTTPTokener extends JSONTokener {

View File

@@ -28,10 +28,12 @@ import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.io.Writer; import java.io.Writer;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.math.*; import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@@ -76,7 +78,7 @@ import java.util.Map;
* </ul> * </ul>
* *
* @author JSON.org * @author JSON.org
* @version 2015-07-22 * @version 2016-07-19
*/ */
public class JSONArray implements Iterable<Object> { public class JSONArray implements Iterable<Object> {
@@ -151,12 +153,11 @@ public class JSONArray implements Iterable<Object> {
* @param collection * @param collection
* A Collection. * A Collection.
*/ */
public JSONArray(Collection<Object> collection) { public JSONArray(Collection<?> collection) {
this.myArrayList = new ArrayList<Object>(); this.myArrayList = new ArrayList<Object>();
if (collection != null) { if (collection != null) {
Iterator<Object> iter = collection.iterator(); for (Object o : collection) {
while (iter.hasNext()) { this.myArrayList.add(JSONObject.wrap(o));
this.myArrayList.add(JSONObject.wrap(iter.next()));
} }
} }
} }
@@ -240,11 +241,15 @@ public class JSONArray implements Iterable<Object> {
public double getDouble(int index) throws JSONException { public double getDouble(int index) throws JSONException {
Object object = this.get(index); Object object = this.get(index);
try { try {
return object instanceof Number ? ((Number) object).doubleValue() if (object instanceof Number) {
: Double.parseDouble((String) object); return ((Number) object).doubleValue();
} catch (Exception e) { } else if (object instanceof String) {
throw new JSONException("JSONArray[" + index + "] is not a number."); return Double.parseDouble((String) object);
} }
} catch (Exception e) {
}
throw new JSONException("JSONArray[" + index + "] is not a number.");
} }
/** /**
@@ -324,11 +329,15 @@ public class JSONArray implements Iterable<Object> {
public int getInt(int index) throws JSONException { public int getInt(int index) throws JSONException {
Object object = this.get(index); Object object = this.get(index);
try { try {
return object instanceof Number ? ((Number) object).intValue() if (object instanceof Number) {
: Integer.parseInt((String) object); return ((Number) object).intValue();
} catch (Exception e) { } else if (object instanceof String) {
throw new JSONException("JSONArray[" + index + "] is not a number."); return Integer.parseInt((String) object);
} }
} catch (Exception e) {
}
throw new JSONException("JSONArray[" + index + "] is not a number.");
} }
/** /**
@@ -380,11 +389,15 @@ public class JSONArray implements Iterable<Object> {
public long getLong(int index) throws JSONException { public long getLong(int index) throws JSONException {
Object object = this.get(index); Object object = this.get(index);
try { try {
return object instanceof Number ? ((Number) object).longValue() if (object instanceof Number) {
: Long.parseLong((String) object); return ((Number) object).longValue();
} catch (Exception e) { } else if (object instanceof String) {
throw new JSONException("JSONArray[" + index + "] is not a number."); return Long.parseLong((String) object);
} }
} catch (Exception e) {
}
throw new JSONException("JSONArray[" + index + "] is not a number.");
} }
/** /**
@@ -485,11 +498,20 @@ public class JSONArray implements Iterable<Object> {
* @return The truth. * @return The truth.
*/ */
public boolean optBoolean(int index, boolean defaultValue) { public boolean optBoolean(int index, boolean defaultValue) {
try { Object object = this.opt(index);
return this.getBoolean(index); if (JSONObject.NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; 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;
} }
/** /**
@@ -517,11 +539,20 @@ public class JSONArray implements Iterable<Object> {
* @return The value. * @return The value.
*/ */
public double optDouble(int index, double defaultValue) { public double optDouble(int index, double defaultValue) {
try { Object object = this.opt(index);
return this.getDouble(index); if (JSONObject.NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).doubleValue();
} else if (object instanceof String) {
return Double.parseDouble((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -549,11 +580,20 @@ public class JSONArray implements Iterable<Object> {
* @return The value. * @return The value.
*/ */
public int optInt(int index, int defaultValue) { public int optInt(int index, int defaultValue) {
try { Object object = this.opt(index);
return this.getInt(index); if (JSONObject.NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).intValue();
} else if (object instanceof String) {
return Integer.parseInt((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -594,7 +634,9 @@ public class JSONArray implements Iterable<Object> {
return myE; return myE;
} }
return Enum.valueOf(clazz, val.toString()); return Enum.valueOf(clazz, val.toString());
} catch (IllegalArgumentException | NullPointerException e) { } catch (IllegalArgumentException e) {
return defaultValue;
} catch (NullPointerException e) {
return defaultValue; return defaultValue;
} }
} }
@@ -612,8 +654,12 @@ public class JSONArray implements Iterable<Object> {
* @return The value. * @return The value.
*/ */
public BigInteger optBigInteger(int index, BigInteger defaultValue) { public BigInteger optBigInteger(int index, BigInteger defaultValue) {
Object object = this.opt(index);
if (JSONObject.NULL.equals(object)) {
return defaultValue;
}
try { try {
return this.getBigInteger(index); return new BigInteger(object.toString());
} catch (Exception e) { } catch (Exception e) {
return defaultValue; return defaultValue;
} }
@@ -631,8 +677,12 @@ public class JSONArray implements Iterable<Object> {
* @return The value. * @return The value.
*/ */
public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) {
Object object = this.opt(index);
if (JSONObject.NULL.equals(object)) {
return defaultValue;
}
try { try {
return this.getBigDecimal(index); return new BigDecimal(object.toString());
} catch (Exception e) { } catch (Exception e) {
return defaultValue; return defaultValue;
} }
@@ -690,11 +740,20 @@ public class JSONArray implements Iterable<Object> {
* @return The value. * @return The value.
*/ */
public long optLong(int index, long defaultValue) { public long optLong(int index, long defaultValue) {
try { Object object = this.opt(index);
return this.getLong(index); if (JSONObject.NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).longValue();
} else if (object instanceof String) {
return Long.parseLong((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -746,7 +805,7 @@ public class JSONArray implements Iterable<Object> {
* A Collection value. * A Collection value.
* @return this. * @return this.
*/ */
public JSONArray put(Collection<Object> value) { public JSONArray put(Collection<?> value) {
this.put(new JSONArray(value)); this.put(new JSONArray(value));
return this; return this;
} }
@@ -799,7 +858,7 @@ public class JSONArray implements Iterable<Object> {
* A Map value. * A Map value.
* @return this. * @return this.
*/ */
public JSONArray put(Map<String, Object> value) { public JSONArray put(Map<?, ?> value) {
this.put(new JSONObject(value)); this.put(new JSONObject(value));
return this; return this;
} }
@@ -848,7 +907,7 @@ public class JSONArray implements Iterable<Object> {
* @throws JSONException * @throws JSONException
* If the index is negative or if the value is not finite. * If the index is negative or if the value is not finite.
*/ */
public JSONArray put(int index, Collection<Object> value) throws JSONException { public JSONArray put(int index, Collection<?> value) throws JSONException {
this.put(index, new JSONArray(value)); this.put(index, new JSONArray(value));
return this; return this;
} }
@@ -920,7 +979,7 @@ public class JSONArray implements Iterable<Object> {
* If the index is negative or if the the value is an invalid * If the index is negative or if the the value is an invalid
* number. * number.
*/ */
public JSONArray put(int index, Map<String, Object> value) throws JSONException { public JSONArray put(int index, Map<?, ?> value) throws JSONException {
this.put(index, new JSONObject(value)); this.put(index, new JSONObject(value));
return this; return this;
} }
@@ -957,6 +1016,46 @@ public class JSONArray implements Iterable<Object> {
return this; return this;
} }
/**
* Creates a JSONPointer using an initialization string and tries to
* match it to an item within this JSONArray. For example, given a
* JSONArray initialized with this document:
* <pre>
* [
* {"b":"c"}
* ]
* </pre>
* and this JSONPointer string:
* <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(String jsonPointer) {
return new JSONPointer(jsonPointer).queryFrom(this);
}
/**
* 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 string representation of the JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
*/
public Object optQuery(String jsonPointer) {
JSONPointer pointer = new JSONPointer(jsonPointer);
try {
return pointer.queryFrom(this);
} catch (JSONPointerException e) {
return null;
}
}
/** /**
* Remove an index and close the hole. * Remove an index and close the hole.
* *
@@ -1038,6 +1137,7 @@ public class JSONArray implements Iterable<Object> {
* @return a printable, displayable, transmittable representation of the * @return a printable, displayable, transmittable representation of the
* array. * array.
*/ */
@Override
public String toString() { public String toString() {
try { try {
return this.toString(0); return this.toString(0);
@@ -1084,6 +1184,8 @@ public class JSONArray implements Iterable<Object> {
* <p> * <p>
* Warning: This method assumes that the data structure is acyclical. * Warning: This method assumes that the data structure is acyclical.
* *
* @param writer
* Writes the serialized JSON
* @param indentFactor * @param indentFactor
* The number of spaces to add to each level of indentation. * The number of spaces to add to each level of indentation.
* @param indent * @param indent
@@ -1091,7 +1193,7 @@ public class JSONArray implements Iterable<Object> {
* @return The writer. * @return The writer.
* @throws JSONException * @throws JSONException
*/ */
Writer write(Writer writer, int indentFactor, int indent) public Writer write(Writer writer, int indentFactor, int indent)
throws JSONException { throws JSONException {
try { try {
boolean commanate = false; boolean commanate = false;
@@ -1127,4 +1229,29 @@ public class JSONArray implements Iterable<Object> {
throw new JSONException(e); throw new JSONException(e);
} }
} }
/**
* Returns a java.util.List containing all of the elements in this array.
* If an element in the array is a JSONArray or JSONObject it will also
* be converted.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @return a java.util.List containing the elements of this array
*/
public List<Object> toList() {
List<Object> results = new ArrayList<Object>(this.myArrayList.size());
for (Object element : this.myArrayList) {
if (element == null || JSONObject.NULL.equals(element)) {
results.add(null);
} else if (element instanceof JSONArray) {
results.add(((JSONArray) element).toList());
} else if (element instanceof JSONObject) {
results.add(((JSONObject) element).toMap());
} else {
results.add(element);
}
}
return results;
}
} }

32
JSONException.java Executable file → Normal file
View File

@@ -4,11 +4,11 @@ package org.json;
* The JSONException is thrown by the JSON.org classes when things are amiss. * The JSONException is thrown by the JSON.org classes when things are amiss.
* *
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class JSONException extends RuntimeException { public class JSONException extends RuntimeException {
/** Serialization ID */
private static final long serialVersionUID = 0; private static final long serialVersionUID = 0;
private Throwable cause;
/** /**
* Constructs a JSONException with an explanatory message. * Constructs a JSONException with an explanatory message.
@@ -16,28 +16,30 @@ public class JSONException extends RuntimeException {
* @param message * @param message
* Detail about the reason for the exception. * Detail about the reason for the exception.
*/ */
public JSONException(String message) { public JSONException(final String message) {
super(message); super(message);
} }
/** /**
* Constructs a new JSONException with the specified cause. * Constructs a JSONException with an explanatory message and cause.
* @param cause The cause. *
* @param message
* Detail about the reason for the exception.
* @param cause
* The cause.
*/ */
public JSONException(Throwable cause) { public JSONException(final String message, final Throwable cause) {
super(cause.getMessage()); super(message, cause);
this.cause = cause;
} }
/** /**
* Returns the cause of this exception or null if the cause is nonexistent * Constructs a new JSONException with the specified cause.
* or unknown.
* *
* @return the cause of this exception or null if the cause is nonexistent * @param cause
* or unknown. * The cause.
*/ */
@Override public JSONException(final Throwable cause) {
public Throwable getCause() { super(cause.getMessage(), cause);
return this.cause;
} }
} }

155
JSONML.java Executable file → Normal file
View File

@@ -33,23 +33,24 @@ import java.util.Iterator;
* the JsonML transform. * the JsonML transform.
* *
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2016-01-30
*/ */
public class JSONML { public class JSONML {
/** /**
* Parse XML values and store them in a JSONArray. * Parse XML values and store them in a JSONArray.
* @param x The XMLTokener containing the source string. * @param x The XMLTokener containing the source string.
* @param arrayForm true if array form, false if object form. * @param arrayForm true if array form, false if object form.
* @param ja The JSONArray that is containing the current tag or null * @param ja The JSONArray that is containing the current tag or null
* if we are at the outermost level. * if we are at the outermost level.
* @param keepStrings Don't type-convert text nodes and attibute values
* @return A JSONArray if the value is the outermost tag, otherwise null. * @return A JSONArray if the value is the outermost tag, otherwise null.
* @throws JSONException * @throws JSONException
*/ */
private static Object parse( private static Object parse(
XMLTokener x, XMLTokener x,
boolean arrayForm, boolean arrayForm,
JSONArray ja JSONArray ja,
boolean keepStrings
) throws JSONException { ) throws JSONException {
String attribute; String attribute;
char c; char c;
@@ -174,7 +175,7 @@ public class JSONML {
if (!(token instanceof String)) { if (!(token instanceof String)) {
throw x.syntaxError("Missing value"); throw x.syntaxError("Missing value");
} }
newjo.accumulate(attribute, XML.stringToValue((String)token)); newjo.accumulate(attribute, keepStrings ? token :JSONObject.stringToValue((String)token));
token = null; token = null;
} else { } else {
newjo.accumulate(attribute, ""); newjo.accumulate(attribute, "");
@@ -193,9 +194,8 @@ public class JSONML {
if (ja == null) { if (ja == null) {
if (arrayForm) { if (arrayForm) {
return newja; return newja;
} else {
return newjo;
} }
return newjo;
} }
// Content, between <...> and </...> // Content, between <...> and </...>
@@ -204,7 +204,7 @@ public class JSONML {
if (token != XML.GT) { if (token != XML.GT) {
throw x.syntaxError("Misshaped tag"); throw x.syntaxError("Misshaped tag");
} }
closeTag = (String)parse(x, arrayForm, newja); closeTag = (String)parse(x, arrayForm, newja, keepStrings);
if (closeTag != null) { if (closeTag != null) {
if (!closeTag.equals(tagName)) { if (!closeTag.equals(tagName)) {
throw x.syntaxError("Mismatched '" + tagName + throw x.syntaxError("Mismatched '" + tagName +
@@ -217,9 +217,8 @@ public class JSONML {
if (ja == null) { if (ja == null) {
if (arrayForm) { if (arrayForm) {
return newja; return newja;
} else {
return newjo;
} }
return newjo;
} }
} }
} }
@@ -227,7 +226,7 @@ public class JSONML {
} else { } else {
if (ja != null) { if (ja != null) {
ja.put(token instanceof String ja.put(token instanceof String
? XML.stringToValue((String)token) ? keepStrings ? token :JSONObject.stringToValue((String)token)
: token); : token);
} }
} }
@@ -245,10 +244,54 @@ public class JSONML {
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored. * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param string The source string. * @param string The source string.
* @return A JSONArray containing the structured data from the XML string. * @return A JSONArray containing the structured data from the XML string.
* @throws JSONException * @throws JSONException Thrown on error converting to a JSONArray
*/ */
public static JSONArray toJSONArray(String string) throws JSONException { public static JSONArray toJSONArray(String string) throws JSONException {
return toJSONArray(new XMLTokener(string)); return (JSONArray)parse(new XMLTokener(string), true, null, false);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONArray using the JsonML transform. Each XML tag is represented as
* a JSONArray in which the first element is the tag name. If the tag has
* attributes, then the second element will be JSONObject containing the
* name/value pairs. If the tag contains children, then strings and
* JSONArrays will represent the child tags.
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* but just leaves it as a string.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param string The source string.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONArray using the JsonML transform. Each XML tag is represented as
* a JSONArray in which the first element is the tag name. If the tag has
* attributes, then the second element will be JSONObject containing the
* name/value pairs. If the tag contains children, then strings and
* JSONArrays will represent the child content and tags.
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* but just leaves it as a string.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param x An XMLTokener.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
return (JSONArray)parse(x, true, null, keepStrings);
} }
@@ -262,28 +305,10 @@ public class JSONML {
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored. * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param x An XMLTokener. * @param x An XMLTokener.
* @return A JSONArray containing the structured data from the XML string. * @return A JSONArray containing the structured data from the XML string.
* @throws JSONException * @throws JSONException Thrown on error converting to a JSONArray
*/ */
public static JSONArray toJSONArray(XMLTokener x) throws JSONException { public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
return (JSONArray)parse(x, true, null); return (JSONArray)parse(x, true, null, false);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param x An XMLTokener of the XML source text.
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException
*/
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
return (JSONObject)parse(x, false, null);
} }
@@ -298,10 +323,68 @@ public class JSONML {
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored. * Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param string The XML source text. * @param string The XML source text.
* @return A JSONObject containing the structured data from the XML string. * @return A JSONObject containing the structured data from the XML string.
* @throws JSONException * @throws JSONException Thrown on error converting to a JSONObject
*/ */
public static JSONObject toJSONObject(String string) throws JSONException { public static JSONObject toJSONObject(String string) throws JSONException {
return toJSONObject(new XMLTokener(string)); return (JSONObject)parse(new XMLTokener(string), false, null, false);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param string The XML source text.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param x An XMLTokener of the XML source text.
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
return (JSONObject)parse(x, false, null, false);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* @param x An XMLTokener of the XML source text.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
return (JSONObject)parse(x, false, null, keepStrings);
} }
@@ -309,7 +392,7 @@ public class JSONML {
* Reverse the JSONML transformation, making an XML text from a JSONArray. * Reverse the JSONML transformation, making an XML text from a JSONArray.
* @param ja A JSONArray. * @param ja A JSONArray.
* @return An XML string. * @return An XML string.
* @throws JSONException * @throws JSONException Thrown on error converting to a string
*/ */
public static String toString(JSONArray ja) throws JSONException { public static String toString(JSONArray ja) throws JSONException {
int i; int i;
@@ -393,7 +476,7 @@ public class JSONML {
* The other properties are attributes with string values. * The other properties are attributes with string values.
* @param jo A JSONObject. * @param jo A JSONObject.
* @return An XML string. * @return An XML string.
* @throws JSONException * @throws JSONException Thrown on error converting to a string
*/ */
public static String toString(JSONObject jo) throws JSONException { public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

250
JSONObject.java Executable file → Normal file
View File

@@ -30,7 +30,8 @@ import java.io.Writer;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.math.*; import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
@@ -92,7 +93,7 @@ import java.util.Set;
* </ul> * </ul>
* *
* @author JSON.org * @author JSON.org
* @version 2015-07-22 * @version 2016-07-19
*/ */
public class JSONObject { public class JSONObject {
/** /**
@@ -131,6 +132,7 @@ public class JSONObject {
* *
* @return The string "null". * @return The string "null".
*/ */
@Override
public String toString() { public String toString() {
return "null"; return "null";
} }
@@ -165,10 +167,6 @@ public class JSONObject {
* A JSONObject. * A JSONObject.
* @param names * @param names
* An array of strings. * An array of strings.
* @throws JSONException
* @exception JSONException
* If a value is a non-finite number or if a name is
* duplicated.
*/ */
public JSONObject(JSONObject jo, String[] names) { public JSONObject(JSONObject jo, String[] names) {
this(); this();
@@ -241,17 +239,14 @@ public class JSONObject {
* @param map * @param map
* A map object that can be used to initialize the contents of * A map object that can be used to initialize the contents of
* the JSONObject. * the JSONObject.
* @throws JSONException
*/ */
public JSONObject(Map<String, Object> map) { public JSONObject(Map<?, ?> map) {
this.map = new HashMap<String, Object>(); this.map = new HashMap<String, Object>();
if (map != null) { if (map != null) {
Iterator<Entry<String, Object>> i = map.entrySet().iterator(); for (final Entry<?, ?> e : map.entrySet()) {
while (i.hasNext()) { final Object value = e.getValue();
Entry<String, Object> entry = i.next();
Object value = entry.getValue();
if (value != null) { if (value != null) {
this.map.put(entry.getKey(), wrap(value)); this.map.put(String.valueOf(e.getKey()), wrap(value));
} }
} }
} }
@@ -582,13 +577,16 @@ public class JSONObject {
public double getDouble(String key) throws JSONException { public double getDouble(String key) throws JSONException {
Object object = this.get(key); Object object = this.get(key);
try { try {
return object instanceof Number ? ((Number) object).doubleValue() if (object instanceof Number) {
: Double.parseDouble((String) object); return ((Number) object).doubleValue();
} else if (object instanceof String) {
return Double.parseDouble((String) object);
}
} catch (Exception e) { } catch (Exception e) {
}
throw new JSONException("JSONObject[" + quote(key) throw new JSONException("JSONObject[" + quote(key)
+ "] is not a number."); + "] is not a number.");
} }
}
/** /**
* Get the int value associated with a key. * Get the int value associated with a key.
@@ -603,12 +601,15 @@ public class JSONObject {
public int getInt(String key) throws JSONException { public int getInt(String key) throws JSONException {
Object object = this.get(key); Object object = this.get(key);
try { try {
return object instanceof Number ? ((Number) object).intValue() if (object instanceof Number) {
: Integer.parseInt((String) object); return ((Number) object).intValue();
} catch (Exception e) { } else if (object instanceof String) {
throw new JSONException("JSONObject[" + quote(key) return Integer.parseInt((String) object);
+ "] is not an int.");
} }
} catch (Exception e) {
}
throw new JSONException("JSONObject[" + quote(key) + "] is not an int.");
} }
/** /**
@@ -660,12 +661,15 @@ public class JSONObject {
public long getLong(String key) throws JSONException { public long getLong(String key) throws JSONException {
Object object = this.get(key); Object object = this.get(key);
try { try {
return object instanceof Number ? ((Number) object).longValue() if (object instanceof Number) {
: Long.parseLong((String) object); return ((Number) object).longValue();
} catch (Exception e) { } else if (object instanceof String) {
throw new JSONException("JSONObject[" + quote(key) return Long.parseLong((String) object);
+ "] is not a long.");
} }
} catch (Exception e) {
}
throw new JSONException("JSONObject[" + quote(key) + "] is not a long.");
} }
/** /**
@@ -907,7 +911,9 @@ public class JSONObject {
return myE; return myE;
} }
return Enum.valueOf(clazz, val.toString()); return Enum.valueOf(clazz, val.toString());
} catch (IllegalArgumentException | NullPointerException e) { } catch (IllegalArgumentException e) {
return defaultValue;
} catch (NullPointerException e) {
return defaultValue; return defaultValue;
} }
} }
@@ -936,11 +942,20 @@ public class JSONObject {
* @return The truth. * @return The truth.
*/ */
public boolean optBoolean(String key, boolean defaultValue) { public boolean optBoolean(String key, boolean defaultValue) {
try { Object object = this.get(key);
return this.getBoolean(key); if (NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; 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;
} }
/** /**
@@ -968,8 +983,12 @@ public class JSONObject {
* @return An object which is the value. * @return An object which is the value.
*/ */
public BigInteger optBigInteger(String key, BigInteger defaultValue) { public BigInteger optBigInteger(String key, BigInteger defaultValue) {
Object object = this.get(key);
if (NULL.equals(object)) {
return defaultValue;
}
try { try {
return this.getBigInteger(key); return new BigInteger(object.toString());
} catch (Exception e) { } catch (Exception e) {
return defaultValue; return defaultValue;
} }
@@ -987,8 +1006,12 @@ public class JSONObject {
* @return An object which is the value. * @return An object which is the value.
*/ */
public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
Object object = this.opt(key);
if (NULL.equals(object)) {
return defaultValue;
}
try { try {
return this.getBigDecimal(key); return new BigDecimal(object.toString());
} catch (Exception e) { } catch (Exception e) {
return defaultValue; return defaultValue;
} }
@@ -1006,11 +1029,20 @@ public class JSONObject {
* @return An object which is the value. * @return An object which is the value.
*/ */
public double optDouble(String key, double defaultValue) { public double optDouble(String key, double defaultValue) {
try { Object object = this.get(key);
return this.getDouble(key); if (NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).doubleValue();
} else if (object instanceof String) {
return Double.parseDouble((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -1038,11 +1070,20 @@ public class JSONObject {
* @return An object which is the value. * @return An object which is the value.
*/ */
public int optInt(String key, int defaultValue) { public int optInt(String key, int defaultValue) {
try { Object object = this.get(key);
return this.getInt(key); if (NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).intValue();
} else if (object instanceof String) {
return Integer.parseInt((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -1096,11 +1137,20 @@ public class JSONObject {
* @return An object which is the value. * @return An object which is the value.
*/ */
public long optLong(String key, long defaultValue) { public long optLong(String key, long defaultValue) {
try { Object object = this.get(key);
return this.getLong(key); if (NULL.equals(object)) {
} catch (Exception e) {
return defaultValue; return defaultValue;
} }
try {
if (object instanceof Number) {
return ((Number) object).longValue();
} else if (object instanceof String) {
return Long.parseLong((String) object);
}
} catch (Exception e) {
}
return defaultValue;
} }
/** /**
@@ -1204,7 +1254,7 @@ public class JSONObject {
* @return this. * @return this.
* @throws JSONException * @throws JSONException
*/ */
public JSONObject put(String key, Collection<Object> value) throws JSONException { public JSONObject put(String key, Collection<?> value) throws JSONException {
this.put(key, new JSONArray(value)); this.put(key, new JSONArray(value));
return this; return this;
} }
@@ -1268,7 +1318,7 @@ public class JSONObject {
* @return this. * @return this.
* @throws JSONException * @throws JSONException
*/ */
public JSONObject put(String key, Map<String, Object> value) throws JSONException { public JSONObject put(String key, Map<?, ?> value) throws JSONException {
this.put(key, new JSONObject(value)); this.put(key, new JSONObject(value));
return this; return this;
} }
@@ -1342,6 +1392,46 @@ public class JSONObject {
return this; return this;
} }
/**
* Creates a JSONPointer using an intialization string and tries to
* match it to an item within this JSONObject. For example, given a
* JSONObject initialized with this document:
* <pre>
* {
* "a":{"b":"c"}
* }
* </pre>
* and this JSONPointer string:
* <pre>
* "/a/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(String jsonPointer) {
return new JSONPointer(jsonPointer).queryFrom(this);
}
/**
* 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 string representation of the JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
*/
public Object optQuery(String jsonPointer) {
JSONPointer pointer = new JSONPointer(jsonPointer);
try {
return pointer.queryFrom(this);
} catch (JSONPointerException e) {
return null;
}
}
/** /**
* Produce a string in double quotes with backslash sequences in all the * Produce a string in double quotes with backslash sequences in all the
* right places. A backslash will be inserted within </, producing <\/, * right places. A backslash will be inserted within </, producing <\/,
@@ -1484,7 +1574,6 @@ public class JSONObject {
* @return A simple JSON value. * @return A simple JSON value.
*/ */
public static Object stringToValue(String string) { public static Object stringToValue(String string) {
Double d;
if (string.equals("")) { if (string.equals("")) {
return string; return string;
} }
@@ -1503,23 +1592,23 @@ public class JSONObject {
* produced, then the value will just be a string. * produced, then the value will just be a string.
*/ */
char b = string.charAt(0); char initial = string.charAt(0);
if ((b >= '0' && b <= '9') || b == '-') { if ((initial >= '0' && initial <= '9') || initial == '-') {
try { try {
if (string.indexOf('.') > -1 || string.indexOf('e') > -1 if (string.indexOf('.') > -1 || string.indexOf('e') > -1
|| string.indexOf('E') > -1) { || string.indexOf('E') > -1
d = Double.valueOf(string); || "-0".equals(string)) {
Double d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) { if (!d.isInfinite() && !d.isNaN()) {
return d; return d;
} }
} else { } else {
Long myLong = new Long(string); Long myLong = new Long(string);
if (string.equals(myLong.toString())) { if (string.equals(myLong.toString())) {
if (myLong == myLong.intValue()) { if (myLong.longValue() == myLong.intValue()) {
return myLong.intValue(); return Integer.valueOf(myLong.intValue());
} else {
return myLong;
} }
return myLong;
} }
} }
} catch (Exception ignore) { } catch (Exception ignore) {
@@ -1586,6 +1675,7 @@ public class JSONObject {
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right * brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>. * brace)</small>.
*/ */
@Override
public String toString() { public String toString() {
try { try {
return this.toString(0); return this.toString(0);
@@ -1663,13 +1753,11 @@ public class JSONObject {
return value.toString(); return value.toString();
} }
if (value instanceof Map) { if (value instanceof Map) {
@SuppressWarnings("unchecked") Map<?, ?> map = (Map<?, ?>) value;
Map<String, Object> map = (Map<String, Object>) value;
return new JSONObject(map).toString(); return new JSONObject(map).toString();
} }
if (value instanceof Collection) { if (value instanceof Collection) {
@SuppressWarnings("unchecked") Collection<?> coll = (Collection<?>) value;
Collection<Object> coll = (Collection<Object>) value;
return new JSONArray(coll).toString(); return new JSONArray(coll).toString();
} }
if (value.getClass().isArray()) { if (value.getClass().isArray()) {
@@ -1707,16 +1795,14 @@ public class JSONObject {
} }
if (object instanceof Collection) { if (object instanceof Collection) {
@SuppressWarnings("unchecked") Collection<?> coll = (Collection<?>) object;
Collection<Object> coll = (Collection<Object>) object;
return new JSONArray(coll); return new JSONArray(coll);
} }
if (object.getClass().isArray()) { if (object.getClass().isArray()) {
return new JSONArray(object); return new JSONArray(object);
} }
if (object instanceof Map) { if (object instanceof Map) {
@SuppressWarnings("unchecked") Map<?, ?> map = (Map<?, ?>) object;
Map<String, Object> map = (Map<String, Object>) object;
return new JSONObject(map); return new JSONObject(map);
} }
Package objectPackage = object.getClass().getPackage(); Package objectPackage = object.getClass().getPackage();
@@ -1755,14 +1841,11 @@ public class JSONObject {
} else if (value instanceof JSONArray) { } else if (value instanceof JSONArray) {
((JSONArray) value).write(writer, indentFactor, indent); ((JSONArray) value).write(writer, indentFactor, indent);
} else if (value instanceof Map) { } else if (value instanceof Map) {
@SuppressWarnings("unchecked") Map<?, ?> map = (Map<?, ?>) value;
Map<String, Object> map = (Map<String, Object>) value;
new JSONObject(map).write(writer, indentFactor, indent); new JSONObject(map).write(writer, indentFactor, indent);
} else if (value instanceof Collection) { } else if (value instanceof Collection) {
@SuppressWarnings("unchecked") Collection<?> coll = (Collection<?>) value;
Collection<Object> coll = (Collection<Object>) value; new JSONArray(coll).write(writer, indentFactor, indent);
new JSONArray(coll).write(writer, indentFactor,
indent);
} else if (value.getClass().isArray()) { } else if (value.getClass().isArray()) {
new JSONArray(value).write(writer, indentFactor, indent); new JSONArray(value).write(writer, indentFactor, indent);
} else if (value instanceof Number) { } else if (value instanceof Number) {
@@ -1795,10 +1878,16 @@ public class JSONObject {
* <p> * <p>
* Warning: This method assumes that the data structure is acyclical. * Warning: This method assumes that the data structure is acyclical.
* *
* @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.
* @return The writer. * @return The writer.
* @throws JSONException * @throws JSONException
*/ */
Writer write(Writer writer, int indentFactor, int indent) public Writer write(Writer writer, int indentFactor, int indent)
throws JSONException { throws JSONException {
try { try {
boolean commanate = false; boolean commanate = false;
@@ -1844,4 +1933,31 @@ public class JSONObject {
throw new JSONException(exception); throw new JSONException(exception);
} }
} }
/**
* Returns a java.util.Map containing all of the entries in this object.
* If an entry in the object is a JSONArray or JSONObject it will also
* be converted.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @return a java.util.Map containing the entries of this object
*/
public Map<String, Object> toMap() {
Map<String, Object> results = new HashMap<String, Object>();
for (Entry<String, Object> entry : this.map.entrySet()) {
Object value;
if (entry.getValue() == null || NULL.equals(entry.getValue())) {
value = null;
} else if (entry.getValue() instanceof JSONObject) {
value = ((JSONObject) entry.getValue()).toMap();
} else if (entry.getValue() instanceof JSONArray) {
value = ((JSONArray) entry.getValue()).toList();
} else {
value = entry.getValue();
}
results.put(entry.getKey(), value);
}
return results;
}
} }

267
JSONPointer.java Normal file
View File

@@ -0,0 +1,267 @@
package org.json;
import static java.lang.String.format;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.
*/
/**
* A JSON Pointer is a simple query language defined for JSON documents by
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>.
*
* In a nutshell, JSONPointer allows the user to navigate into a JSON document
* using strings, and retrieve targeted objects, like a simple form of XPATH.
* Path segments are separated by the '/' char, which signifies the root of
* the document when it appears as the first char of the string. Array
* elements are navigated using ordinals, counting from 0. JSONPointer strings
* may be extended to any arbitrary number of segments. If the navigation
* is successful, the matched item is returned. A matched item may be a
* JSONObject, a JSONArray, or a JSON value. If the JSONPointer string building
* fails, an appropriate exception is thrown. If the navigation fails to find
* a match, a JSONPointerException is thrown.
*
* @author JSON.org
* @version 2016-05-14
*/
public class JSONPointer {
// used for URL encoding and decoding
private static final String ENCODING = "utf-8";
/**
* This class allows the user to build a JSONPointer in steps, using
* exactly one segment in each step.
*/
public static class Builder {
// Segments for the eventual JSONPointer string
private final List<String> refTokens = new ArrayList<String>();
/**
* Creates a {@code JSONPointer} instance using the tokens previously set using the
* {@link #append(String)} method calls.
*/
public JSONPointer build() {
return new JSONPointer(refTokens);
}
/**
* Adds an arbitary 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
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
* need to escape it as {@code "a~0b"}.
*
* @param token the new token to be appended to the list
* @return {@code this}
* @throws NullPointerException if {@code token} is null
*/
public Builder append(String token) {
if (token == null) {
throw new NullPointerException("token cannot be null");
}
refTokens.add(token);
return this;
}
/**
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
* denote an array index.
*
* @param arrayIndex the array index to be added to the token list
* @return {@code this}
*/
public Builder append(int arrayIndex) {
refTokens.add(String.valueOf(arrayIndex));
return this;
}
}
/**
* Static factory method for {@link Builder}. Example usage:
*
* <pre><code>
* JSONPointer pointer = JSONPointer.builder()
* .append("obj")
* .append("other~key").append("another/key")
* .append("\"")
* .append(0)
* .build();
* </code></pre>
*
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
* {@link Builder#append(String)} calls.
*/
public static Builder builder() {
return new Builder();
}
// Segments for the JSONPointer string
private final List<String> refTokens;
/**
* Pre-parses and initializes a new {@code JSONPointer} instance. If you want to
* evaluate the same JSON Pointer on different JSON documents then it is recommended
* to keep the {@code JSONPointer} instances due to performance considerations.
*
* @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) {
if (pointer == null) {
throw new NullPointerException("pointer cannot be null");
}
if (pointer.isEmpty()) {
refTokens = Collections.emptyList();
return;
}
if (pointer.startsWith("#/")) {
pointer = pointer.substring(2);
try {
pointer = URLDecoder.decode(pointer, ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
} else if (pointer.startsWith("/")) {
pointer = 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));
}
}
public JSONPointer(List<String> refTokens) {
this.refTokens = new ArrayList<String>(refTokens);
}
private String unescape(String token) {
return token.replace("~1", "/").replace("~0", "~")
.replace("\\\"", "\"")
.replace("\\\\", "\\");
}
/**
* Evaluates this JSON Pointer on the given {@code document}. The {@code document}
* is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty
* JSON Pointer ({@code ""}) can be evaluated on any JSON values and in such case the
* returned value will be {@code document} itself.
*
* @param document the JSON document which should be the subject of querying.
* @return the result of the evaluation
* @throws JSONPointerException if an error occurs during evaluation
*/
public Object queryFrom(Object document) {
if (refTokens.isEmpty()) {
return document;
}
Object current = document;
for (String token : refTokens) {
if (current instanceof JSONObject) {
current = ((JSONObject) current).opt(unescape(token));
} else if (current instanceof JSONArray) {
current = readByIndexToken(current, token);
} else {
throw new JSONPointerException(format(
"value [%s] is not an array or object therefore its key %s cannot be resolved", current,
token));
}
}
return current;
}
/**
* Matches a JSONArray element by ordinal position
* @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
*/
private Object readByIndexToken(Object current, String indexToken) {
try {
int index = Integer.parseInt(indexToken);
JSONArray currentArr = (JSONArray) current;
if (index >= currentArr.length()) {
throw new JSONPointerException(format("index %d is out of bounds - the array has %d elements", index,
currentArr.length()));
}
return currentArr.get(index);
} catch (NumberFormatException e) {
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
}
}
/**
* Returns a string representing the JSONPointer path value using string
* representation
*/
@Override
public String toString() {
StringBuilder rval = new StringBuilder("");
for (String token: refTokens) {
rval.append('/').append(escape(token));
}
return rval.toString();
}
/**
* Escapes path segment values to an unambiguous form.
* The escape char to be inserted is '~'. The chars to be escaped
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
* and double quote chars are also escaped.
* @param token the JSONPointer segment value to be escaped
* @return the escaped value for the token
*/
private String escape(String token) {
return token.replace("~", "~0")
.replace("/", "~1")
.replace("\\", "\\\\")
.replace("\"", "\\\"");
}
/**
* Returns a string representing the JSONPointer path value using URI
* fragment identifier representation
*/
public String toURIFragment() {
try {
StringBuilder rval = new StringBuilder("#");
for (String token : refTokens) {
rval.append('/').append(URLEncoder.encode(token, ENCODING));
}
return rval.toString();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}

45
JSONPointerException.java Normal file
View File

@@ -0,0 +1,45 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.
*/
/**
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs
* during evaluating a pointer.
*
* @author JSON.org
* @version 2016-05-13
*/
public class JSONPointerException extends JSONException {
private static final long serialVersionUID = 8872944667561856751L;
public JSONPointerException(String message) {
super(message);
}
public JSONPointerException(String message, Throwable cause) {
super(message, cause);
}
}

0
JSONString.java Executable file → Normal file
View File

2
JSONStringer.java Executable file → Normal file
View File

@@ -54,7 +54,7 @@ import java.io.StringWriter;
* <p> * <p>
* This can sometimes be easier than using a JSONObject to build a string. * This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org * @author JSON.org
* @version 2008-09-18 * @version 2015-12-09
*/ */
public class JSONStringer extends JSONWriter { public class JSONStringer extends JSONWriter {
/** /**

View File

@@ -71,7 +71,7 @@ public class JSONTokener {
* Construct a JSONTokener from an InputStream. * Construct a JSONTokener from an InputStream.
* @param inputStream The source. * @param inputStream The source.
*/ */
public JSONTokener(InputStream inputStream) throws JSONException { public JSONTokener(InputStream inputStream) {
this(new InputStreamReader(inputStream)); this(new InputStreamReader(inputStream));
} }
@@ -90,6 +90,8 @@ public class JSONTokener {
* Back up one character. This provides a sort of lookahead capability, * Back up one character. This provides a sort of lookahead capability,
* so that you can test for a digit or letter before attempting to parse * so that you can test for a digit or letter before attempting to parse
* the next number or identifier. * the next number or identifier.
* @throws JSONException Thrown if trying to step back more than 1 step
* or if already at the start of the string
*/ */
public void back() throws JSONException { public void back() throws JSONException {
if (this.usePrevious || this.index <= 0) { if (this.usePrevious || this.index <= 0) {
@@ -121,6 +123,9 @@ public class JSONTokener {
return -1; return -1;
} }
/**
* @return true if at the end of the file and we didn't step back
*/
public boolean end() { public boolean end() {
return this.eof && !this.usePrevious; return this.eof && !this.usePrevious;
} }
@@ -130,6 +135,8 @@ public class JSONTokener {
* Determine if the source string still contains characters that next() * Determine if the source string still contains characters that next()
* can consume. * can consume.
* @return true if not yet at the end of the source. * @return true if not yet at the end of the source.
* @throws JSONException thrown if there is an error stepping forward
* or backward while checking for more data.
*/ */
public boolean more() throws JSONException { public boolean more() throws JSONException {
this.next(); this.next();
@@ -145,6 +152,7 @@ public class JSONTokener {
* Get the next character in the source string. * Get the next character in the source string.
* *
* @return The next character, or 0 if past the end of the source string. * @return The next character, or 0 if past the end of the source string.
* @throws JSONException Thrown if there is an error reading the source string.
*/ */
public char next() throws JSONException { public char next() throws JSONException {
int c; int c;
@@ -225,7 +233,7 @@ public class JSONTokener {
/** /**
* Get the next char in the string, skipping whitespace. * Get the next char in the string, skipping whitespace.
* @throws JSONException * @throws JSONException Thrown if there is an error reading the source string.
* @return A character, or 0 if there are no more characters. * @return A character, or 0 if there are no more characters.
*/ */
public char nextClean() throws JSONException { public char nextClean() throws JSONException {
@@ -278,7 +286,11 @@ public class JSONTokener {
sb.append('\r'); sb.append('\r');
break; break;
case 'u': case 'u':
try {
sb.append((char)Integer.parseInt(this.next(4), 16)); sb.append((char)Integer.parseInt(this.next(4), 16));
} catch (NumberFormatException e) {
throw this.syntaxError("Illegal escape.", e);
}
break; break;
case '"': case '"':
case '\'': case '\'':
@@ -305,6 +317,8 @@ public class JSONTokener {
* end of line, whichever comes first. * end of line, whichever comes first.
* @param delimiter A delimiter character. * @param delimiter A delimiter character.
* @return A string. * @return A string.
* @throws JSONException Thrown if there is an error while searching
* for the delimiter
*/ */
public String nextTo(char delimiter) throws JSONException { public String nextTo(char delimiter) throws JSONException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
@@ -326,6 +340,8 @@ public class JSONTokener {
* characters or the end of line, whichever comes first. * characters or the end of line, whichever comes first.
* @param delimiters A set of delimiter characters. * @param delimiters A set of delimiter characters.
* @return A string, trimmed. * @return A string, trimmed.
* @throws JSONException Thrown if there is an error while searching
* for the delimiter
*/ */
public String nextTo(String delimiters) throws JSONException { public String nextTo(String delimiters) throws JSONException {
char c; char c;
@@ -397,6 +413,8 @@ public class JSONTokener {
* @param to A character to skip to. * @param to A character to skip to.
* @return The requested character, or zero if the requested character * @return The requested character, or zero if the requested character
* is not found. * is not found.
* @throws JSONException Thrown if there is an error while searching
* for the to character
*/ */
public char skipTo(char to) throws JSONException { public char skipTo(char to) throws JSONException {
char c; char c;
@@ -433,12 +451,23 @@ public class JSONTokener {
return new JSONException(message + this.toString()); return new JSONException(message + this.toString());
} }
/**
* Make a JSONException to signal a syntax error.
*
* @param message The error message.
* @param causedBy The throwable that caused the error.
* @return A JSONException object, suitable for throwing
*/
public JSONException syntaxError(String message, Throwable causedBy) {
return new JSONException(message + this.toString(), causedBy);
}
/** /**
* Make a printable string of this JSONTokener. * Make a printable string of this JSONTokener.
* *
* @return " at {index} [character {character} line {line}]" * @return " at {index} [character {character} line {line}]"
*/ */
@Override
public String toString() { public String toString() {
return " at " + this.index + " [character " + this.character + " line " + return " at " + this.index + " [character " + this.character + " line " +
this.line + "]"; this.line + "]";

2
JSONWriter.java Executable file → Normal file
View File

@@ -54,7 +54,7 @@ SOFTWARE.
* <p> * <p>
* This can sometimes be easier than using a JSONObject to build a string. * This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org * @author JSON.org
* @version 2011-11-24 * @version 2015-12-09
*/ */
public class JSONWriter { public class JSONWriter {
private static final int maxdepth = 200; private static final int maxdepth = 200;

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
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.

47
README Executable file → Normal file
View File

@@ -15,7 +15,7 @@ The license includes this restriction: "The software shall be used for good,
not evil." If your conscience cannot live with that, then choose a different not evil." If your conscience cannot live with that, then choose a different
package. package.
The package compiles on Java 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
@@ -32,6 +32,10 @@ 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
[JSON Pointer (RFC 6901)](https://tools.ietf.org/html/rfc6901). Supports
JSON Pointers both in the form of string representation and URI fragment
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.
@@ -61,4 +65,43 @@ 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 JSON-java pull requests with the code in this project: https://github.com/stleary/JSON-Java-unit-test Unit tests are maintained in a separate project. Contributing developers can test
JSON-java pull requests with the code in this project:
https://github.com/stleary/JSON-Java-unit-test
Numeric types in this package comply with 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
(https://tools.ietf.org/html/rfc7159#section-6).
This package fully supports Integer, Long, and Double Java types. Partial support
for BigInteger and BigDecimal values in JSONObject and JSONArray objects is provided
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
removed in some future release.
In compliance with RFC7159 page 10 section 9, the parser is more lax with what is valid
JSON than the Generator. For Example, the tab character (U+0009) is allowed when reading
JSON Text strings, but when output by the Generator, tab is properly converted to \t in
the string. Other instances may occur where reading invalid JSON text does not cause an
error to be generated. Malformed JSON Texts such as missing end " (quote) on strings or
invalid number formats (1.2e6.3) will cause errors as such documents can not be read
reliably.
Release history:
20160807 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
20160212 Java 1.6 compatibility, OSGi bundle. Contains the latest code as of 12 Feb, 2016.
20151123 JSONObject and JSONArray initialization with generics. Contains the
latest code as of 23 Nov, 2015.
20150729 Checkpoint for Maven central repository release. Contains the latest code
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:
https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.json%22%20AND%20a%3A%22json%22

288
XML.java Executable file → Normal file
View File

@@ -1,7 +1,7 @@
package org.json; package org.json;
/* /*
Copyright (c) 2002 JSON.org Copyright (c) 2015 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -27,11 +27,13 @@ SOFTWARE.
import java.util.Iterator; import java.util.Iterator;
/** /**
* This provides static methods to convert an XML text into a JSONObject, * This provides static methods to convert an XML text into a JSONObject, and to
* and to covert a JSONObject into an XML text. * covert a JSONObject into an XML text.
*
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2016-01-30
*/ */
@SuppressWarnings("boxing")
public class XML { public class XML {
/** The Character '&amp;'. */ /** The Character '&amp;'. */
@@ -63,13 +65,16 @@ public class XML {
/** /**
* Replace special characters with XML escapes: * Replace special characters with XML escapes:
*
* <pre> * <pre>
* &amp; <small>(ampersand)</small> is replaced by &amp;amp; * &amp; <small>(ampersand)</small> is replaced by &amp;amp;
* &lt; <small>(less than)</small> is replaced by &amp;lt; * &lt; <small>(less than)</small> is replaced by &amp;lt;
* &gt; <small>(greater than)</small> is replaced by &amp;gt; * &gt; <small>(greater than)</small> is replaced by &amp;gt;
* &quot; <small>(double quote)</small> is replaced by &amp;quot; * &quot; <small>(double quote)</small> is replaced by &amp;quot;
* </pre> * </pre>
* @param string The string to be escaped. *
* @param string
* The string to be escaped.
* @return The escaped string. * @return The escaped string.
*/ */
public static String escape(String string) { public static String escape(String string) {
@@ -100,10 +105,12 @@ public class XML {
} }
/** /**
* Throw an exception if the string contains whitespace. * Throw an exception if the string contains whitespace. Whitespace is not
* Whitespace is not allowed in tagNames and attributes. * allowed in tagNames and attributes.
* @param string A string. *
* @throws JSONException * @param string
* A string.
* @throws JSONException Thrown if the string contains whitespace or is empty.
*/ */
public static void noSpace(String string) throws JSONException { public static void noSpace(String string) throws JSONException {
int i, length = string.length(); int i, length = string.length();
@@ -112,22 +119,26 @@ public class XML {
} }
for (i = 0; i < length; i += 1) { for (i = 0; i < length; i += 1) {
if (Character.isWhitespace(string.charAt(i))) { if (Character.isWhitespace(string.charAt(i))) {
throw new JSONException("'" + string + throw new JSONException("'" + string
"' contains a space character."); + "' contains a space character.");
} }
} }
} }
/** /**
* Scan the content following the named tag, attaching it to the context. * Scan the content following the named tag, attaching it to the context.
* @param x The XMLTokener containing the source string. *
* @param context The JSONObject that will include the new material. * @param x
* @param name The tag name. * The XMLTokener containing the source string.
* @param context
* The JSONObject that will include the new material.
* @param name
* The tag name.
* @return true if the close tag is processed. * @return true if the close tag is processed.
* @throws JSONException * @throws JSONException
*/ */
private static boolean parse(XMLTokener x, JSONObject context, private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings)
String name) throws JSONException { throws JSONException {
char c; char c;
int i; int i;
JSONObject jsonobject = null; JSONObject jsonobject = null;
@@ -135,19 +146,19 @@ public class XML {
String tagName; String tagName;
Object token; Object token;
// Test for and skip past these forms: // Test for and skip past these forms:
// <!-- ... --> // <!-- ... -->
// <! ... > // <! ... >
// <![ ... ]]> // <![ ... ]]>
// <? ... ?> // <? ... ?>
// Report errors for these forms: // Report errors for these forms:
// <> // <>
// <= // <=
// << // <<
token = x.nextToken(); token = x.nextToken();
// <! // <!
if (token == BANG) { if (token == BANG) {
c = x.next(); c = x.next();
@@ -184,13 +195,12 @@ public class XML {
return false; return false;
} else if (token == QUEST) { } else if (token == QUEST) {
// <? // <?
x.skipPast("?>"); x.skipPast("?>");
return false; return false;
} else if (token == SLASH) { } else if (token == SLASH) {
// Close tag </ // Close tag </
token = x.nextToken(); token = x.nextToken();
if (name == null) { if (name == null) {
@@ -207,10 +217,10 @@ public class XML {
} else if (token instanceof Character) { } else if (token instanceof Character) {
throw x.syntaxError("Misshaped tag"); throw x.syntaxError("Misshaped tag");
// Open tag < // Open tag <
} else { } else {
tagName = (String)token; tagName = (String) token;
token = null; token = null;
jsonobject = new JSONObject(); jsonobject = new JSONObject();
for (;;) { for (;;) {
@@ -218,10 +228,9 @@ public class XML {
token = x.nextToken(); token = x.nextToken();
} }
// attribute = value // attribute = value
if (token instanceof String) { if (token instanceof String) {
string = (String)token; string = (String) token;
token = x.nextToken(); token = x.nextToken();
if (token == EQ) { if (token == EQ) {
token = x.nextToken(); token = x.nextToken();
@@ -229,15 +238,15 @@ public class XML {
throw x.syntaxError("Missing value"); throw x.syntaxError("Missing value");
} }
jsonobject.accumulate(string, jsonobject.accumulate(string,
XML.stringToValue((String)token)); keepStrings ? token : JSONObject.stringToValue((String) token));
token = null; token = null;
} else { } else {
jsonobject.accumulate(string, ""); jsonobject.accumulate(string, "");
} }
// Empty tag <.../>
} else if (token == SLASH) { } else if (token == SLASH) {
// Empty tag <.../>
if (x.nextToken() != GT) { if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag"); throw x.syntaxError("Misshaped tag");
} }
@@ -248,9 +257,8 @@ public class XML {
} }
return false; return false;
// Content, between <...> and </...>
} else if (token == GT) { } else if (token == GT) {
// Content, between <...> and </...>
for (;;) { for (;;) {
token = x.nextContent(); token = x.nextContent();
if (token == null) { if (token == null) {
@@ -259,20 +267,19 @@ public class XML {
} }
return false; return false;
} else if (token instanceof String) { } else if (token instanceof String) {
string = (String)token; string = (String) token;
if (string.length() > 0) { if (string.length() > 0) {
jsonobject.accumulate("content", jsonobject.accumulate("content",
XML.stringToValue(string)); keepStrings ? token : JSONObject.stringToValue(string));
} }
// Nested element
} else if (token == LT) { } else if (token == LT) {
if (parse(x, jsonobject, tagName)) { // Nested element
if (parse(x, jsonobject, tagName,keepStrings)) {
if (jsonobject.length() == 0) { if (jsonobject.length() == 0) {
context.accumulate(tagName, ""); context.accumulate(tagName, "");
} else if (jsonobject.length() == 1 && } else if (jsonobject.length() == 1
jsonobject.opt("content") != null) { && jsonobject.opt("content") != null) {
context.accumulate(tagName, context.accumulate(tagName,
jsonobject.opt("content")); jsonobject.opt("content"));
} else { } else {
@@ -289,159 +296,154 @@ public class XML {
} }
} }
/**
* This method has been deprecated in favor of the
* {@link JSONObject.stringToValue(String)} method. Use it instead.
*
* @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);
}
/** /**
* Try to convert a string into a number, boolean, or null. If the string * Convert a well-formed (but not necessarily valid) XML string into a
* can't be converted, return the string. This is much less ambitious than * JSONObject. Some information may be lost in this transformation because
* JSONObject.stringToValue, especially because it does not attempt to * JSON is a data format and XML is a document format. XML uses elements,
* convert plus forms, octal forms, hex forms, or E forms lacking decimal * attributes, and content text, while JSON uses unordered collections of
* points. * name/value pairs and arrays of values. JSON does not does not like to
* @param string A String. * distinguish between elements and attributes. Sequences of similar
* @return A simple JSON value. * elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* are ignored.
*
* @param string
* The source string.
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown if there is an errors while parsing the string
*/ */
public static Object stringToValue(String string) { public static JSONObject toJSONObject(String string) throws JSONException {
if ("true".equalsIgnoreCase(string)) { return toJSONObject(string, false);
return Boolean.TRUE;
}
if ("false".equalsIgnoreCase(string)) {
return Boolean.FALSE;
}
if ("null".equalsIgnoreCase(string)) {
return JSONObject.NULL;
}
// If it might be a number, try converting it, first as a Long, and then as a
// Double. If that doesn't work, return the string.
try {
char initial = string.charAt(0);
if (initial == '-' || (initial >= '0' && initial <= '9')) {
Long value = new Long(string);
if (value.toString().equals(string)) {
return value;
}
}
} catch (Exception ignore) {
try {
Double value = new Double(string);
if (value.toString().equals(string)) {
return value;
}
} catch (Exception ignoreAlso) {
}
}
return string;
} }
/** /**
* Convert a well-formed (but not necessarily valid) XML string into a * Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject. Some information may be lost in this transformation * JSONObject. Some information may be lost in this transformation because
* because JSON is a data format and XML is a document format. XML uses * JSON is a data format and XML is a document format. XML uses elements,
* elements, attributes, and content text, while JSON uses unordered * attributes, and content text, while JSON uses unordered collections of
* collections of name/value pairs and arrays of values. JSON does not * name/value pairs and arrays of values. JSON does not does not like to
* does not like to distinguish between elements and attributes. * distinguish between elements and attributes. Sequences of similar
* Sequences of similar elements are represented as JSONArrays. Content * elements are represented as JSONArrays. Content text may be placed in a
* text may be placed in a "content" member. Comments, prologs, DTDs, and * "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* <code>&lt;[ [ ]]></code> are ignored. * are ignored.
* @param string The source string. *
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
* numbers but will instead be the exact value as seen in the XML document.
*
* @param string
* The source string.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string. * @return A JSONObject containing the structured data from the XML string.
* @throws JSONException * @throws JSONException Thrown if there is an errors while parsing the string
*/ */
public static JSONObject toJSONObject(String string) 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("<")) {
parse(x, jo, null); parse(x, jo, null, keepStrings);
} }
return jo; return jo;
} }
/** /**
* Convert a JSONObject into a well-formed, element-normal XML string. * Convert a JSONObject into a well-formed, element-normal XML string.
* @param object A JSONObject. *
* @param object
* A JSONObject.
* @return A string. * @return A string.
* @throws JSONException * @throws JSONException Thrown if there is an error parsing the string
*/ */
public static String toString(Object object) throws JSONException { public static String toString(Object object) throws JSONException {
return toString(object, null); return toString(object, null);
} }
/** /**
* Convert a JSONObject into a well-formed, element-normal XML string. * Convert a JSONObject into a well-formed, element-normal XML string.
* @param object A JSONObject. *
* @param tagName The optional name of the enclosing tag. * @param object
* A JSONObject.
* @param tagName
* The optional name of the enclosing tag.
* @return A string. * @return A string.
* @throws JSONException * @throws JSONException Thrown if there is an error parsing the string
*/ */
public static String toString(Object object, String tagName) public static String toString(Object object, String tagName)
throws JSONException { throws JSONException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
int i;
JSONArray ja; JSONArray ja;
JSONObject jo; JSONObject jo;
String key; String key;
Iterator<String> keys; Iterator<String> keys;
int length;
String string; String string;
Object value; Object value;
if (object instanceof JSONObject) { if (object instanceof JSONObject) {
// Emit <tagName> // Emit <tagName>
if (tagName != null) { if (tagName != null) {
sb.append('<'); sb.append('<');
sb.append(tagName); sb.append(tagName);
sb.append('>'); sb.append('>');
} }
// Loop thru the keys. // Loop thru the keys.
jo = (JSONObject) object;
jo = (JSONObject)object;
keys = jo.keys(); keys = jo.keys();
while (keys.hasNext()) { while (keys.hasNext()) {
key = keys.next(); key = keys.next();
value = jo.opt(key); value = jo.opt(key);
if (value == null) { if (value == null) {
value = ""; value = "";
} else if (value.getClass().isArray()) {
value = new JSONArray(value);
} }
string = value instanceof String ? (String)value : null; string = value instanceof String ? (String) value : null;
// Emit content in body
// Emit content in body
if ("content".equals(key)) { if ("content".equals(key)) {
if (value instanceof JSONArray) { if (value instanceof JSONArray) {
ja = (JSONArray)value; ja = (JSONArray) value;
length = ja.length(); int i = 0;
for (i = 0; i < length; i += 1) { for (Object val : ja) {
if (i > 0) { if (i > 0) {
sb.append('\n'); sb.append('\n');
} }
sb.append(escape(ja.get(i).toString())); sb.append(escape(val.toString()));
i++;
} }
} else { } else {
sb.append(escape(value.toString())); sb.append(escape(value.toString()));
} }
// Emit an array of similar keys // Emit an array of similar keys
} else if (value instanceof JSONArray) { } else if (value instanceof JSONArray) {
ja = (JSONArray)value; ja = (JSONArray) value;
length = ja.length(); for (Object val : ja) {
for (i = 0; i < length; i += 1) { if (val instanceof JSONArray) {
value = ja.get(i);
if (value instanceof JSONArray) {
sb.append('<'); sb.append('<');
sb.append(key); sb.append(key);
sb.append('>'); sb.append('>');
sb.append(toString(value)); sb.append(toString(val));
sb.append("</"); sb.append("</");
sb.append(key); sb.append(key);
sb.append('>'); sb.append('>');
} else { } else {
sb.append(toString(value, key)); sb.append(toString(val, key));
} }
} }
} else if ("".equals(value)) { } else if ("".equals(value)) {
@@ -449,7 +451,7 @@ public class XML {
sb.append(key); sb.append(key);
sb.append("/>"); sb.append("/>");
// Emit a new tag <k> // Emit a new tag <k>
} else { } else {
sb.append(toString(value, key)); sb.append(toString(value, key));
@@ -457,34 +459,36 @@ public class XML {
} }
if (tagName != null) { if (tagName != null) {
// Emit the </tagname> close tag // Emit the </tagname> close tag
sb.append("</"); sb.append("</");
sb.append(tagName); sb.append(tagName);
sb.append('>'); sb.append('>');
} }
return sb.toString(); return sb.toString();
// XML does not have good support for arrays. If an array appears in a place }
// where XML is lacking, synthesize an <array> element.
} else { if (object != null) {
if (object.getClass().isArray()) { if (object.getClass().isArray()) {
object = new JSONArray(object); object = new JSONArray(object);
} }
if (object instanceof JSONArray) { if (object instanceof JSONArray) {
ja = (JSONArray)object; ja = (JSONArray) object;
length = ja.length(); for (Object val : ja) {
for (i = 0; i < length; i += 1) { // XML does not have good support for arrays. If an array
sb.append(toString(ja.opt(i), tagName == null ? "array" : tagName)); // appears in a place where XML is lacking, synthesize an
// <array> element.
sb.append(toString(val, tagName == null ? "array" : tagName));
} }
return sb.toString(); return sb.toString();
} else { }
}
string = (object == null) ? "null" : escape(object.toString()); string = (object == null) ? "null" : escape(object.toString());
return (tagName == null) ? "\"" + string + "\"" : return (tagName == null) ? "\"" + string + "\""
(string.length() == 0) ? "<" + tagName + "/>" : : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
"<" + tagName + ">" + string + "</" + tagName + ">"; + ">" + string + "</" + tagName + ">";
}
}
} }
} }

2
XMLTokener.java Executable file → Normal file
View File

@@ -28,7 +28,7 @@ SOFTWARE.
* The XMLTokener extends the JSONTokener to provide additional methods * The XMLTokener extends the JSONTokener to provide additional methods
* for the parsing of XML texts. * for the parsing of XML texts.
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2015-12-09
*/ */
public class XMLTokener extends JSONTokener { public class XMLTokener extends JSONTokener {