From 07b2d65e30c4a7ffa789360c2f13e5eb5e417339 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Wed, 27 Jan 2016 10:39:31 -0500 Subject: [PATCH 01/34] Fixes #187 -0 now returns as a double. --- JSONObject.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index 2f613f8..7b71f37 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -30,7 +30,8 @@ import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.math.*; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; @@ -1500,7 +1501,8 @@ public class JSONObject { if ((b >= '0' && b <= '9') || b == '-') { try { if (string.indexOf('.') > -1 || string.indexOf('e') > -1 - || string.indexOf('E') > -1) { + || string.indexOf('E') > -1 + || "0".equals(string.substring(1))) { d = Double.valueOf(string); if (!d.isInfinite() && !d.isNaN()) { return d; @@ -1508,11 +1510,10 @@ public class JSONObject { } else { Long myLong = new Long(string); if (string.equals(myLong.toString())) { - if (myLong == myLong.intValue()) { - return myLong.intValue(); - } else { - return myLong; + if (myLong.longValue() == myLong.intValue()) { + return Integer.valueOf(myLong.intValue()); } + return myLong; } } } catch (Exception ignore) { From 39b1c0cb6682310aef7f7579836eb9561e3ad275 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Wed, 27 Jan 2016 10:45:23 -0500 Subject: [PATCH 02/34] fixes error in -0 check --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index 7b71f37..dc47cd2 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1502,7 +1502,7 @@ public class JSONObject { try { if (string.indexOf('.') > -1 || string.indexOf('e') > -1 || string.indexOf('E') > -1 - || "0".equals(string.substring(1))) { + || "-0".equals(string)) { d = Double.valueOf(string); if (!d.isInfinite() && !d.isNaN()) { return d; From 3007fc8ebe591b93caa9f6ab6b46e8677058a7a8 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Wed, 27 Jan 2016 15:03:19 -0500 Subject: [PATCH 03/34] Removes custom XML stringToValue method in favor of keeping a consistent implementation in JSONObject --- JSONML.java | 4 ++-- JSONObject.java | 7 +++---- XML.java | 48 ++---------------------------------------------- 3 files changed, 7 insertions(+), 52 deletions(-) diff --git a/JSONML.java b/JSONML.java index a4b874d..8d5e6c6 100644 --- a/JSONML.java +++ b/JSONML.java @@ -174,7 +174,7 @@ public class JSONML { if (!(token instanceof String)) { throw x.syntaxError("Missing value"); } - newjo.accumulate(attribute, XML.stringToValue((String)token)); + newjo.accumulate(attribute, JSONObject.stringToValue((String)token)); token = null; } else { newjo.accumulate(attribute, ""); @@ -227,7 +227,7 @@ public class JSONML { } else { if (ja != null) { ja.put(token instanceof String - ? XML.stringToValue((String)token) + ? JSONObject.stringToValue((String)token) : token); } } diff --git a/JSONObject.java b/JSONObject.java index dc47cd2..c37de6b 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1478,7 +1478,6 @@ public class JSONObject { * @return A simple JSON value. */ public static Object stringToValue(String string) { - Double d; if (string.equals("")) { return string; } @@ -1497,13 +1496,13 @@ public class JSONObject { * produced, then the value will just be a string. */ - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '-') { + char initial = string.charAt(0); + if ((initial >= '0' && initial <= '9') || initial == '-') { try { if (string.indexOf('.') > -1 || string.indexOf('e') > -1 || string.indexOf('E') > -1 || "-0".equals(string)) { - d = Double.valueOf(string); + Double d = Double.valueOf(string); if (!d.isInfinite() && !d.isNaN()) { return d; } diff --git a/XML.java b/XML.java index f14463c..c0e84f0 100644 --- a/XML.java +++ b/XML.java @@ -238,7 +238,7 @@ public class XML { throw x.syntaxError("Missing value"); } jsonobject.accumulate(string, - XML.stringToValue((String) token)); + JSONObject.stringToValue((String) token)); token = null; } else { jsonobject.accumulate(string, ""); @@ -270,7 +270,7 @@ public class XML { string = (String) token; if (string.length() > 0) { jsonobject.accumulate("content", - XML.stringToValue(string)); + JSONObject.stringToValue(string)); } } else if (token == LT) { @@ -296,50 +296,6 @@ public class XML { } } - /** - * Try to convert a string into a number, boolean, or null. If the string - * can't be converted, return the string. This is much less ambitious than - * JSONObject.stringToValue, especially because it does not attempt to - * convert plus forms, octal forms, hex forms, or E forms lacking decimal - * points. - * - * @param string - * A String. - * @return A simple JSON value. - */ - public static Object stringToValue(String string) { - if ("true".equalsIgnoreCase(string)) { - 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 * JSONObject. Some information may be lost in this transformation because From c2b3f2bdb164dc884efc5903ce807f7698f5dd94 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Wed, 27 Jan 2016 15:21:11 -0500 Subject: [PATCH 04/34] adds back in the XML.stringToValue method, but deprecates it. --- XML.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/XML.java b/XML.java index c0e84f0..a45ef15 100644 --- a/XML.java +++ b/XML.java @@ -295,6 +295,18 @@ 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 + * @return JSON value of this string or the string + */ + public static Object stringToValue(String string) { + return JSONObject.stringToValue(string); + } /** * Convert a well-formed (but not necessarily valid) XML string into a From 62486fdea41f3aed606f2b69f4576b313077fad8 Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 30 Jan 2016 15:44:08 -0600 Subject: [PATCH 05/34] Version date --- JSONML.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONML.java b/JSONML.java index 8d5e6c6..9acf21d 100644 --- a/JSONML.java +++ b/JSONML.java @@ -33,7 +33,7 @@ import java.util.Iterator; * the JsonML transform. * * @author JSON.org - * @version 2015-12-09 + * @version 2016-01-30 */ public class JSONML { From 93c79ca5668c7179e99c34a1cb750d6d7066c39c Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 30 Jan 2016 15:44:41 -0600 Subject: [PATCH 06/34] Version date --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index c37de6b..27be3ec 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -93,7 +93,7 @@ import java.util.Set; * * * @author JSON.org - * @version 2015-12-09 + * @version 2015-01-30 */ public class JSONObject { /** From ba2585fe6c18eee9873d1e3a98c459f9e59dc02b Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 30 Jan 2016 15:45:11 -0600 Subject: [PATCH 07/34] Version date --- XML.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XML.java b/XML.java index a45ef15..bbcda3b 100644 --- a/XML.java +++ b/XML.java @@ -31,7 +31,7 @@ import java.util.Iterator; * covert a JSONObject into an XML text. * * @author JSON.org - * @version 2016-01-01 + * @version 2016-01-30 */ @SuppressWarnings("boxing") public class XML { From 60349ece54204f7ee261b3e6fd2b058733dce388 Mon Sep 17 00:00:00 2001 From: skreutzer Date: Mon, 8 Feb 2016 23:30:27 -0500 Subject: [PATCH 08/34] Java 1.6 compatibility. --- JSONArray.java | 6 ++++-- JSONObject.java | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index a3df975..f29085b 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -76,7 +76,7 @@ import java.util.Map; * * * @author JSON.org - * @version 2015-10-29 + * @version 2016-02-08 */ public class JSONArray implements Iterable { @@ -593,7 +593,9 @@ public class JSONArray implements Iterable { return myE; } return Enum.valueOf(clazz, val.toString()); - } catch (IllegalArgumentException | NullPointerException e) { + } catch (IllegalArgumentException e) { + return defaultValue; + } catch (NullPointerException e) { return defaultValue; } } diff --git a/JSONObject.java b/JSONObject.java index 27be3ec..1ce2540 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -93,7 +93,7 @@ import java.util.Set; * * * @author JSON.org - * @version 2015-01-30 + * @version 2016-02-08 */ public class JSONObject { /** @@ -901,7 +901,9 @@ public class JSONObject { return myE; } return Enum.valueOf(clazz, val.toString()); - } catch (IllegalArgumentException | NullPointerException e) { + } catch (IllegalArgumentException e) { + return defaultValue; + } catch (NullPointerException e) { return defaultValue; } } From 2657915293eca812160b9e8d8a143e181aab63d1 Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 13 Feb 2016 22:26:45 -0600 Subject: [PATCH 09/34] Update README Include some text about 1.6 compatibility and add the latest release information. --- README | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README b/README index 4d6751c..8ac6ccd 100644 --- a/README +++ b/README @@ -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 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 @@ -32,7 +32,6 @@ tokens. It can be constructed from a String, Reader, or InputStream. JSONException.java: The JSONException is the standard exception type thrown by this package. - JSONString.java: The JSONString interface requires a toJSONString method, allowing an object to provide its own serialization. @@ -73,8 +72,13 @@ This package fully supports Integer, Long, and Double Java types. Partial suppor 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. + Release history: +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. From f024b52108ee75b5eb1a14584e034e268b26637e Mon Sep 17 00:00:00 2001 From: Joe Ferner Date: Fri, 26 Feb 2016 23:46:41 -0500 Subject: [PATCH 10/34] Adds JSONArray toList method and JSONObject toMap method --- JSONArray.java | 33 ++++++++++++++++++++++++++++----- JSONObject.java | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index f29085b..702742c 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -28,11 +28,9 @@ import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Array; -import java.math.*; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; /** * A JSONArray is an ordered sequence of values. Its external text form is a @@ -1130,4 +1128,29 @@ public class JSONArray implements Iterable { 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. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a java.util.List containing the elements of this array + */ + public List toList() { + List results = new ArrayList(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; + } } diff --git a/JSONObject.java b/JSONObject.java index 1ce2540..444e4fa 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -32,15 +32,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.ResourceBundle; -import java.util.Set; /** * A JSONObject is an unordered collection of name/value pairs. Its external @@ -1838,4 +1831,31 @@ public class JSONObject { throw new JSONException(exception); } } + + /** + * Returns a java.util.Map containing all of the entrys in this object. + * If an entry in the object is a JSONArray or JSONObject it will also + * be converted. + *

+ * Warning: This method assumes that the data structure is acyclical. + * + * @return a java.util.Map containing the entrys of this object + */ + public Map toMap() { + Map results = new HashMap<>(); + for (Entry 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; + } } From 2f3af56535d105c5f998fbabecc968361a4472ac Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 5 Mar 2016 15:19:45 -0600 Subject: [PATCH 11/34] Update date of merge. --- JSONArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONArray.java b/JSONArray.java index 702742c..7aaa611 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -74,7 +74,7 @@ import java.util.*; * * * @author JSON.org - * @version 2016-02-08 + * @version 2016-03-05 */ public class JSONArray implements Iterable { From 25a87975beb7e826b148b5f69d77337f68ae8832 Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Sat, 5 Mar 2016 15:20:20 -0600 Subject: [PATCH 12/34] Update date of merge. --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index 444e4fa..852358b 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -86,7 +86,7 @@ import java.util.Map.Entry; * * * @author JSON.org - * @version 2016-02-08 + * @version 2016-03-05 */ public class JSONObject { /** From 86cbfbc8642a5d4c3c8dff0c59d9fc36f1fa2843 Mon Sep 17 00:00:00 2001 From: Brian Russell Date: Tue, 12 Apr 2016 14:13:15 -0400 Subject: [PATCH 13/34] Added CSV change to CDL.java --- CDL.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CDL.java b/CDL.java index aaa39cd..47b84ae 100644 --- a/CDL.java +++ b/CDL.java @@ -69,7 +69,12 @@ public class CDL { for (;;) { c = x.next(); if (c == q) { - break; + //Handle escaped double-quote + if(x.next() != '\"') + { + x.back(); + break; + } } if (c == 0 || c == '\n' || c == '\r') { throw x.syntaxError("Missing close quote '" + q + "'."); From 612e41950ca5f70df58ed07499003e092a27b325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Sun, 17 Apr 2016 23:21:38 +0200 Subject: [PATCH 14/34] initial implementation of JSONPointer --- JSONPointer.java | 61 +++++++++++++++++++++++++++++++++++++++ JSONPointerException.java | 21 ++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 JSONPointer.java create mode 100644 JSONPointerException.java diff --git a/JSONPointer.java b/JSONPointer.java new file mode 100644 index 0000000..a05db98 --- /dev/null +++ b/JSONPointer.java @@ -0,0 +1,61 @@ +package org.json; + +import static java.lang.String.format; +import static java.util.Collections.emptyList; + +import java.util.ArrayList; +import java.util.List; + +public class JSONPointer { + + private List refTokens; + + public JSONPointer(String pointer) { + if (pointer == null) { + throw new NullPointerException("pointer cannot be null"); + } + if (pointer.isEmpty()) { + refTokens = emptyList(); + return; + } + if (pointer.startsWith("#/")) { + pointer = pointer.substring(2); + } else if (pointer.startsWith("/")) { + pointer = pointer.substring(1); + } else { + throw new IllegalArgumentException("a JSON pointer should start with '/' or '#/'"); + } + refTokens = new ArrayList(); + for (String token : pointer.split("/")) { + refTokens.add(unescape(token)); + } + } + + private String unescape(String token) { + return token.replace("~1", "/").replace("~0", "~"); + } + + public Object queryFrom(JSONObject 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, unescape(token)); + } + } + return current; + } + + private Object readByIndexToken(Object current, String indexToken) { + try { + return ((JSONArray) current).opt(Integer.parseInt(unescape(indexToken))); + } catch (NumberFormatException e) { + throw new JSONPointerException(format("%s is not an array index", unescape(indexToken)), e); + } + } + +} diff --git a/JSONPointerException.java b/JSONPointerException.java new file mode 100644 index 0000000..599f0bb --- /dev/null +++ b/JSONPointerException.java @@ -0,0 +1,21 @@ +package org.json; + +/** + * The JSONPointerException is thrown by {@link JSONPointer} if an error occurs + * during evaluating a pointer. + * + * @author erosb + * + */ +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); + } + +} From 5bee7e3b45984b7119b97f9cc48c879466c18064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Tue, 26 Apr 2016 23:00:16 +0200 Subject: [PATCH 15/34] escape handling improvements & URL fragment notation handling --- JSONPointer.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/JSONPointer.java b/JSONPointer.java index a05db98..85451e6 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -3,6 +3,8 @@ package org.json; import static java.lang.String.format; import static java.util.Collections.emptyList; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; @@ -20,6 +22,11 @@ public class JSONPointer { } if (pointer.startsWith("#/")) { pointer = pointer.substring(2); + try { + pointer = URLDecoder.decode(pointer, "utf-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } } else if (pointer.startsWith("/")) { pointer = pointer.substring(1); } else { @@ -32,7 +39,9 @@ public class JSONPointer { } private String unescape(String token) { - return token.replace("~1", "/").replace("~0", "~"); + return token.replace("~1", "/").replace("~0", "~") + .replace("\\\"", "\"") + .replace("\\\\", "\\"); } public Object queryFrom(JSONObject document) { From 792c6f6a9c423a58f4d5e812999e7c69da157f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Tue, 26 Apr 2016 23:32:15 +0200 Subject: [PATCH 16/34] improved failure handling --- JSONPointer.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/JSONPointer.java b/JSONPointer.java index 85451e6..275c036 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -53,7 +53,11 @@ public class JSONPointer { if (current instanceof JSONObject) { current = ((JSONObject) current).opt(unescape(token)); } else if (current instanceof JSONArray) { - current = readByIndexToken(current, unescape(token)); + 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; @@ -61,10 +65,15 @@ public class JSONPointer { private Object readByIndexToken(Object current, String indexToken) { try { - return ((JSONArray) current).opt(Integer.parseInt(unescape(indexToken))); + 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", unescape(indexToken)), e); + throw new JSONPointerException(format("%s is not an array index", indexToken), e); } } - } From 45bd72c15df1bdeae561ff25f0fd1827e405431a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Tue, 26 Apr 2016 23:48:14 +0200 Subject: [PATCH 17/34] added JSONObject#query() and JSONPointer#query() methods --- JSONArray.java | 10 +++++++++- JSONObject.java | 13 ++++++++++++- JSONPointer.java | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index 7aaa611..f338a2d 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -30,7 +30,11 @@ import java.io.Writer; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * A JSONArray is an ordered sequence of values. Its external text form is a @@ -955,6 +959,10 @@ public class JSONArray implements Iterable { } return this; } + + public Object query(String jsonPointer) { + return new JSONPointer(jsonPointer).queryFrom(this); + } /** * Remove an index and close the hole. diff --git a/JSONObject.java b/JSONObject.java index 852358b..ab113f3 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -32,8 +32,15 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.*; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Map; import java.util.Map.Entry; +import java.util.ResourceBundle; +import java.util.Set; /** * A JSONObject is an unordered collection of name/value pairs. Its external @@ -1330,6 +1337,10 @@ public class JSONObject { } return this; } + + public Object query(String jsonPointer) { + return new JSONPointer(jsonPointer).queryFrom(this); + } /** * Produce a string in double quotes with backslash sequences in all the diff --git a/JSONPointer.java b/JSONPointer.java index 275c036..e5bc125 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -44,7 +44,7 @@ public class JSONPointer { .replace("\\\\", "\\"); } - public Object queryFrom(JSONObject document) { + public Object queryFrom(Object document) { if (refTokens.isEmpty()) { return document; } From 5223aadd67df246b4347731bd025dbbb0d4d53a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Wed, 27 Apr 2016 00:10:06 +0200 Subject: [PATCH 18/34] added some javadoc to JSONPointer --- JSONPointer.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/JSONPointer.java b/JSONPointer.java index e5bc125..2b8bcd3 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -8,10 +8,22 @@ import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; +/** + * A JSON Pointer is a simple query language defined for JSON documents by + * RFC 6901. + */ public class JSONPointer { private List 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"); @@ -44,6 +56,16 @@ public class JSONPointer { .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; From bff352791c4753dfe871a1bf6093f60fb6213447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Wed, 27 Apr 2016 00:10:45 +0200 Subject: [PATCH 19/34] removed @author tag from JSONPointerException --- JSONPointerException.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/JSONPointerException.java b/JSONPointerException.java index 599f0bb..a7840cb 100644 --- a/JSONPointerException.java +++ b/JSONPointerException.java @@ -3,9 +3,6 @@ package org.json; /** * The JSONPointerException is thrown by {@link JSONPointer} if an error occurs * during evaluating a pointer. - * - * @author erosb - * */ public class JSONPointerException extends JSONException { private static final long serialVersionUID = 8872944667561856751L; From c1a789a70c1a9d0a055a9d1756597beeeab95a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Wed, 27 Apr 2016 00:11:47 +0200 Subject: [PATCH 20/34] adding missing license headers --- JSONPointer.java | 24 ++++++++++++++++++++++++ JSONPointerException.java | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/JSONPointer.java b/JSONPointer.java index 2b8bcd3..b6d1307 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -8,6 +8,30 @@ import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; +/* +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 * RFC 6901. diff --git a/JSONPointerException.java b/JSONPointerException.java index a7840cb..e3d20a9 100644 --- a/JSONPointerException.java +++ b/JSONPointerException.java @@ -1,5 +1,29 @@ 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. From cbb1546c530d73d55c51b903b9c14962f4f40671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Thu, 28 Apr 2016 16:45:17 +0200 Subject: [PATCH 21/34] README improvements for stleary/JSON-Java#218 --- README | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README b/README index 8ac6ccd..fb0e9e4 100644 --- a/README +++ b/README @@ -32,6 +32,11 @@ tokens. It can be constructed from a String, Reader, or InputStream. JSONException.java: The JSONException is the standard exception type thrown 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, allowing an object to provide its own serialization. From 1ca8933a8ffeae7be679668e71a64bbb9da0a121 Mon Sep 17 00:00:00 2001 From: stleary Date: Thu, 28 Apr 2016 22:12:16 -0500 Subject: [PATCH 22/34] fix to compile with 1.6.0_45 --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index 852358b..03fb346 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1842,7 +1842,7 @@ public class JSONObject { * @return a java.util.Map containing the entrys of this object */ public Map toMap() { - Map results = new HashMap<>(); + Map results = new HashMap(); for (Entry entry : this.map.entrySet()) { Object value; if (entry.getValue() == null || NULL.equals(entry.getValue())) { From cad23423abe55fb128f2d85a575c8de63f9173bb Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Mon, 2 May 2016 22:11:20 -0500 Subject: [PATCH 23/34] Update JSONObject.java Forgot to update date of last change --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index 03fb346..3cac6e0 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -86,7 +86,7 @@ import java.util.Map.Entry; * * * @author JSON.org - * @version 2016-03-05 + * @version 2016-05-01 */ public class JSONObject { /** From f21ffbe1898fbeff8eb059f2da20d3d5b7329601 Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Mon, 2 May 2016 22:12:29 -0500 Subject: [PATCH 24/34] Update CDL.java Date of last change. --- CDL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CDL.java b/CDL.java index 47b84ae..6a82764 100644 --- a/CDL.java +++ b/CDL.java @@ -41,7 +41,7 @@ SOFTWARE. * The names for the elements in the JSONObjects can be taken from the names * in the first row. * @author JSON.org - * @version 2015-12-09 + * @version 2016-05-01 */ public class CDL { From d833c2d8de86be697bbc1e9a416736cefafcf320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Tue, 3 May 2016 23:18:05 +0200 Subject: [PATCH 25/34] added builder class for JSONPointer, and implemented toString() and toURIFragment() --- JSONPointer.java | 64 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/JSONPointer.java b/JSONPointer.java index b6d1307..eb0b3e9 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -5,6 +5,7 @@ import static java.util.Collections.emptyList; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; @@ -37,8 +38,34 @@ SOFTWARE. * RFC 6901. */ public class JSONPointer { + + private static final String ENCODING = "utf-8"; - private List refTokens; + public static class Builder { + + private final List refTokens = new ArrayList(); + + public Builder append(String token) { + refTokens.add(token); + return this; + } + + public JSONPointer build() { + return new JSONPointer(refTokens); + } + + public Builder append(int arrayIndex) { + refTokens.add(String.valueOf(arrayIndex)); + return this; + } + + } + + public static Builder builder() { + return new Builder(); + } + + private final List refTokens; /** * Pre-parses and initializes a new {@code JSONPointer} instance. If you want to @@ -59,7 +86,7 @@ public class JSONPointer { if (pointer.startsWith("#/")) { pointer = pointer.substring(2); try { - pointer = URLDecoder.decode(pointer, "utf-8"); + pointer = URLDecoder.decode(pointer, ENCODING); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } @@ -74,6 +101,10 @@ public class JSONPointer { } } + public JSONPointer(List refTokens) { + this.refTokens = refTokens; + } + private String unescape(String token) { return token.replace("~1", "/").replace("~0", "~") .replace("\\\"", "\"") @@ -122,4 +153,33 @@ public class JSONPointer { throw new JSONPointerException(format("%s is not an array index", indexToken), e); } } + + @Override + public String toString() { + StringBuilder rval = new StringBuilder(""); + for (String token: refTokens) { + rval.append('/').append(escape(token)); + } + return rval.toString(); + } + + private String escape(String token) { + return token.replace("~", "~0") + .replace("/", "~1") + .replace("\\", "\\\\") + .replace("\"", "\\\""); + } + + 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); + } + } + } From 5ae6a66e38518ea97a81bd475df6ebadaf982095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Tue, 3 May 2016 23:41:51 +0200 Subject: [PATCH 26/34] added javadoc & null check in Builder#append(String) --- JSONPointer.java | 53 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/JSONPointer.java b/JSONPointer.java index eb0b3e9..ddfe40b 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -44,16 +44,42 @@ public class JSONPointer { public static class Builder { private final List refTokens = new ArrayList(); - - public Builder append(String token) { - refTokens.add(token); - return this; - } - + + /** + * 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; @@ -61,6 +87,21 @@ public class JSONPointer { } + /** + * Static factory method for {@link Builder}. Example usage: + * + *

+     * JSONPointer pointer = JSONPointer.builder()
+     *       .append("obj")
+     *       .append("other~key").append("another/key")
+     *       .append("\"")
+     *       .append(0)
+     *       .build();
+     * 
+ * + * @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(); } From c044eb14dd388da8f9a570d8b1f79d1952d42e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Thu, 5 May 2016 15:59:43 +0200 Subject: [PATCH 27/34] added copying to JSONPointer constructor --- JSONPointer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONPointer.java b/JSONPointer.java index ddfe40b..820a448 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -143,7 +143,7 @@ public class JSONPointer { } public JSONPointer(List refTokens) { - this.refTokens = refTokens; + this.refTokens = new ArrayList(refTokens); } private String unescape(String token) { From 4a458a9f1c39e004d87bae8dc3a74793d577a97e Mon Sep 17 00:00:00 2001 From: stleary Date: Sat, 14 May 2016 09:22:18 -0500 Subject: [PATCH 28/34] add timestamps to recent commits, javadocs for JSONObject, JSONArray queryFrom() methods --- JSONArray.java | 21 ++++++++++++++++++++- JSONObject.java | 23 +++++++++++++++++++++-- JSONPointer.java | 5 ++++- JSONPointerException.java | 3 +++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index f338a2d..b2f505e 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -78,7 +78,7 @@ import java.util.Map; * * * @author JSON.org - * @version 2016-03-05 + * @version 2016-05-13 */ public class JSONArray implements Iterable { @@ -960,6 +960,25 @@ public class JSONArray implements Iterable { return this; } + /** + * Creates a JSONPointer using an intialization string and tries to + * match it to an item within this JSONArray. For example, given a + * JSONArray initialized with this document: + *
+     * [
+     *     {"b":"c"}
+     * ]
+     * 
+ * and this JSONPointer string: + *
+     * "/0/b"
+     * 
+ * 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); } diff --git a/JSONObject.java b/JSONObject.java index f2f0f7d..4244220 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -93,7 +93,7 @@ import java.util.Set; * * * @author JSON.org - * @version 2016-05-01 + * @version 2016-05-13 */ public class JSONObject { /** @@ -1337,7 +1337,26 @@ public class JSONObject { } 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: + *
+     * {
+     *     "a":{"b":"c"}
+     * }
+     * 
+ * and this JSONPointer string: + *
+     * "/a/b"
+     * 
+ * 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); } diff --git a/JSONPointer.java b/JSONPointer.java index 820a448..e27ad9e 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -35,7 +35,10 @@ SOFTWARE. /** * A JSON Pointer is a simple query language defined for JSON documents by - * RFC 6901. + * RFC 6901. + * + * @author JSON.org + * @version 2016-05-13 */ public class JSONPointer { diff --git a/JSONPointerException.java b/JSONPointerException.java index e3d20a9..0ce1aeb 100644 --- a/JSONPointerException.java +++ b/JSONPointerException.java @@ -27,6 +27,9 @@ 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; From 9a81b40334ff2eba531478d013654c5d1b12ad24 Mon Sep 17 00:00:00 2001 From: stleary Date: Sat, 14 May 2016 11:09:51 -0500 Subject: [PATCH 29/34] added some JavaDocs --- JSONPointer.java | 62 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/JSONPointer.java b/JSONPointer.java index e27ad9e..563047b 100644 --- a/JSONPointer.java +++ b/JSONPointer.java @@ -1,13 +1,11 @@ package org.json; import static java.lang.String.format; -import static java.util.Collections.emptyList; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /* Copyright (c) 2002 JSON.org @@ -36,18 +34,35 @@ SOFTWARE. /** * A JSON Pointer is a simple query language defined for JSON documents by * RFC 6901. - * + * + * 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-13 + * @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 refTokens = new ArrayList(); - + /** * Creates a {@code JSONPointer} instance using the tokens previously set using the * {@link #append(String)} method calls. @@ -87,9 +102,8 @@ public class JSONPointer { refTokens.add(String.valueOf(arrayIndex)); return this; } - } - + /** * Static factory method for {@link Builder}. Example usage: * @@ -109,6 +123,7 @@ public class JSONPointer { return new Builder(); } + // Segments for the JSONPointer string private final List refTokens; /** @@ -124,7 +139,7 @@ public class JSONPointer { throw new NullPointerException("pointer cannot be null"); } if (pointer.isEmpty()) { - refTokens = emptyList(); + refTokens = Collections.emptyList(); return; } if (pointer.startsWith("#/")) { @@ -184,6 +199,13 @@ public class JSONPointer { 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); @@ -197,7 +219,11 @@ public class JSONPointer { 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(""); @@ -207,6 +233,14 @@ public class JSONPointer { 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") @@ -214,6 +248,10 @@ public class JSONPointer { .replace("\"", "\\\""); } + /** + * Returns a string representing the JSONPointer path value using URI + * fragment identifier representation + */ public String toURIFragment() { try { StringBuilder rval = new StringBuilder("#"); From 56be31e7a83223162a29e51f2daaa9eb9ad2de3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bence=20Er=C5=91s?= Date: Mon, 16 May 2016 14:53:34 +0200 Subject: [PATCH 30/34] fixing stleary/JSON-Java#233 --- JSONArray.java | 17 +++++++++++++++++ JSONObject.java | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/JSONArray.java b/JSONArray.java index f338a2d..4ddd1cd 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -963,6 +963,23 @@ public class JSONArray implements Iterable { 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. diff --git a/JSONObject.java b/JSONObject.java index ab113f3..e3f2270 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1341,6 +1341,23 @@ public class JSONObject { 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 From 808320801a0102945fa45ebea6f686e73d8fea4c Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Fri, 20 May 2016 21:09:53 -0500 Subject: [PATCH 31/34] Update JSONArray.java Update version timestamp --- JSONArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONArray.java b/JSONArray.java index 133c87d..776a2bd 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -78,7 +78,7 @@ import java.util.Map; * * * @author JSON.org - * @version 2016-05-13 + * @version 2016-05-20 */ public class JSONArray implements Iterable { From 612dafc750cc9b75d1d3ae0496fb48940ce64974 Mon Sep 17 00:00:00 2001 From: Sean Leary Date: Fri, 20 May 2016 21:10:17 -0500 Subject: [PATCH 32/34] Update JSONObject.java --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index 52dd401..aa227ff 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -93,7 +93,7 @@ import java.util.Set; * * * @author JSON.org - * @version 2016-05-13 + * @version 2016-05-20 */ public class JSONObject { /** From dfa651e7777f9bd3bb7b8b8f80cac6af90b2ac45 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Thu, 2 Jun 2016 15:56:48 +0200 Subject: [PATCH 33/34] Make nextString throw a JSONException instead of a NumberFormatException for malformed input. --- JSONTokener.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/JSONTokener.java b/JSONTokener.java index 32548ed..92fe5c1 100644 --- a/JSONTokener.java +++ b/JSONTokener.java @@ -278,7 +278,11 @@ public class JSONTokener { sb.append('\r'); break; case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); + try { + sb.append((char)Integer.parseInt(this.next(4), 16)); + } catch (NumberFormatException e) { + throw this.syntaxError("Illegal escape."); + } break; case '"': case '\'': From 16a86d73df322dc696e0dc38b4fdd49f65175497 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Thu, 2 Jun 2016 16:11:15 +0200 Subject: [PATCH 34/34] Pass in the throwable that caused the error. --- JSONTokener.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/JSONTokener.java b/JSONTokener.java index 92fe5c1..7702b19 100644 --- a/JSONTokener.java +++ b/JSONTokener.java @@ -281,7 +281,7 @@ public class JSONTokener { try { sb.append((char)Integer.parseInt(this.next(4), 16)); } catch (NumberFormatException e) { - throw this.syntaxError("Illegal escape."); + throw this.syntaxError("Illegal escape.", e); } break; case '"': @@ -437,6 +437,16 @@ public class JSONTokener { 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.