From 4731ea876a120370f88d57610e3602b5c4fdb850 Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Mon, 15 Mar 2010 23:47:57 -0700 Subject: [PATCH] First half of JSON Javadocs. Change-Id: I277ec3b35a28802dd7b7f82c1f4bbadbd3cc4c65 --- .../json/src/main/java/org/json/JSONException.java | 4 +- .../json/src/main/java/org/json/JSONStringer.java | 96 ++++++++++++++- .../json/src/main/java/org/json/JSONTokener.java | 133 ++++++++++++++++++--- 3 files changed, 214 insertions(+), 19 deletions(-) diff --git a/libcore/json/src/main/java/org/json/JSONException.java b/libcore/json/src/main/java/org/json/JSONException.java index e1efd9fc1..ddd10168a 100644 --- a/libcore/json/src/main/java/org/json/JSONException.java +++ b/libcore/json/src/main/java/org/json/JSONException.java @@ -23,8 +23,8 @@ package org.json; * diff --git a/libcore/json/src/main/java/org/json/JSONStringer.java b/libcore/json/src/main/java/org/json/JSONStringer.java index fb60bd1bb..fa22397e5 100644 --- a/libcore/json/src/main/java/org/json/JSONStringer.java +++ b/libcore/json/src/main/java/org/json/JSONStringer.java @@ -23,7 +23,40 @@ import java.util.List; // Note: this class was written without inspecting the non-free org.json sourcecode. /** + * Implements {@link JSONObject#toString()} and {@link JSONArray#toString}. Most + * application developers should use those methods directly and disregard this + * API. For example:
+ * JSONObject object = ...
+ * String json = object.toString();
* + *

Stringers only encode well-formed JSON strings. In particular: + *

+ * Calls that would result in a malformed JSON string will fail with a + * {@link JSONException}. + * + *

This class provides no facility for pretty-printing (ie. indenting) + * output. To encode indented output, use {@link JSONObject#toString(int)} or + * {@link JSONArray#toString(int)}. + * + *

Some implementations of the API support at most 20 levels of nesting. + * Attempts to create more than 20 levels of nesting may fail with a {@link + * JSONException}. + * + *

Each stringer may be used to encode a single top level value. Instances of + * this class are not thread safe. Although this class is nonfinal, it was not + * designed for inheritance and should not be subclassed. In particular, + * self-use by overridable methods is not specified. See Effective Java + * Item 17, "Design and Document or inheritance or else prohibit it" for further + * information. */ public class JSONStringer { @@ -96,18 +129,40 @@ public class JSONStringer { indent = new String(indentChars); } + /** + * Begins encoding a new array. Each call to this method must be paired with + * a call to {@link #endArray()}. + * + * @return this stringer. + */ public JSONStringer array() throws JSONException { return open(Scope.EMPTY_ARRAY, "["); } + /** + * Ends encoding the current array. + * + * @return this stringer. + */ public JSONStringer endArray() throws JSONException { return close(Scope.EMPTY_ARRAY, Scope.NONEMPTY_ARRAY, "]"); } + /** + * Begins encoding a new object. Each call to this method must be paired + * with a call to {@link #endObject()}. + * + * @return this stringer. + */ public JSONStringer object() throws JSONException { return open(Scope.EMPTY_OBJECT, "{"); } + /** + * Ends encoding the current object. + * + * @return this stringer. + */ public JSONStringer endObject() throws JSONException { return close(Scope.EMPTY_OBJECT, Scope.NONEMPTY_OBJECT, "}"); } @@ -161,6 +216,14 @@ public class JSONStringer { stack.set(stack.size() - 1, topOfStack); } + /** + * Encodes {@code value}. + * + * @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs} + * or {@link Double#isInfinite() infinities}. + * @return this stringer. + */ public JSONStringer value(Object value) throws JSONException { if (stack.isEmpty()) { throw new JSONException("Nesting problem"); @@ -192,6 +255,11 @@ public class JSONStringer { return this; } + /** + * Encodes {@code value} to this stringer. + * + * @return this stringer. + */ public JSONStringer value(boolean value) throws JSONException { if (stack.isEmpty()) { throw new JSONException("Nesting problem"); @@ -201,6 +269,13 @@ public class JSONStringer { return this; } + /** + * Encodes {@code value} to this stringer. + * + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this stringer. + */ public JSONStringer value(double value) throws JSONException { if (stack.isEmpty()) { throw new JSONException("Nesting problem"); @@ -210,6 +285,11 @@ public class JSONStringer { return this; } + /** + * Encodes {@code value} to this stringer. + * + * @return this stringer. + */ public JSONStringer value(long value) throws JSONException { if (stack.isEmpty()) { throw new JSONException("Nesting problem"); @@ -281,6 +361,12 @@ public class JSONStringer { } } + /** + * Encodes the key (property name) to this stringer. + * + * @param name the name of the forthcoming value. May not be null. + * @return this stringer. + */ public JSONStringer key(String name) throws JSONException { if (name == null) { throw new JSONException("Names must be non-null"); @@ -331,8 +417,14 @@ public class JSONStringer { } /** - * Although it contradicts the general contract of {@link Object#toString}, - * this method returns null if the stringer contains no data. + * Returns the encoded JSON string. + * + *

If invoked with unterminated arrays or unclosed objects, this method's + * return value is undefined. + * + *

Warning: although it contradicts the general contract + * of {@link Object#toString}, this method returns null if the stringer + * contains no data. */ @Override public String toString() { return out.length() == 0 ? null : out.toString(); diff --git a/libcore/json/src/main/java/org/json/JSONTokener.java b/libcore/json/src/main/java/org/json/JSONTokener.java index e249c74d1..d5d2dd289 100644 --- a/libcore/json/src/main/java/org/json/JSONTokener.java +++ b/libcore/json/src/main/java/org/json/JSONTokener.java @@ -19,7 +19,28 @@ package org.json; // Note: this class was written without inspecting the non-free org.json sourcecode. /** + * Parses a JSON (RFC 4627) + * encoded string into the corresponding object. Most clients of + * this class will use only need the {@link #JSONTokener(String) constructor} + * and {@link #nextValue} method. Example usage:

+ * String json = "{"
+ *         + "  \"query\": \"Pizza\", "
+ *         + "  \"locations\": [ 94043, 90210 ] "
+ *         + "}";
  *
+ * JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
+ * String query = object.getString("query");
+ * JSONArray locations = object.getJSONArray("locations");
+ * + *

This parser is lenient. A successful parse does not necessarily indicate + * that the input string is valid JSON. + * + *

Each tokener may be used to parse a single JSON string. Instances of this + * class are not thread safe. Although this class is nonfinal, it was not + * designed for inheritance and should not be subclassed. In particular, + * self-use by overridable methods is not specified. See Effective Java + * Item 17, "Design and Document or inheritance or else prohibit it" for further + * information. */ public class JSONTokener { @@ -32,10 +53,22 @@ public class JSONTokener { */ private int pos; + /** + * @param in JSON encoded string. Null is not permitted and will yield a + * tokener that throws {@code NullPointerExceptions} when methods are + * called. + */ public JSONTokener(String in) { this.in = in; } + /** + * Returns the next value from the input. + * + * @return a {@link JSONObject}, {@link JSONArray}, String, Boolean, + * Integer, Long, Double or {@link JSONObject#NULL}. + * @throws JSONException if the input is malformed. + */ public Object nextValue() throws JSONException { int c = nextCleanInternal(); switch (c) { @@ -121,8 +154,12 @@ public class JSONTokener { } /** + * Returns the string up to but not including {@code quote}, unescaping any + * character escape sequences encountered along the way. The opening quote + * should have already been read. This consumes the closing quote, but does + * not include it in the returned string. * - * + * @param quote either ' or ". * @throws NumberFormatException if any unicode escape sequences are * malformed. */ @@ -264,9 +301,8 @@ public class JSONTokener { } /** - * Returns text from the current position until the first of any of the - * given characters or a newline character, excluding that character. The - * position is advanced to the excluded character. + * Returns the string up to but not including any of the given characters or + * a newline character. This does not consume the excluded character. */ private String nextToInternal(String excluded) { int start = pos; @@ -378,10 +414,17 @@ public class JSONTokener { } } - public JSONException syntaxError(String text) { - return new JSONException(text + this); + /** + * Returns an exception containing the given message plus the current + * position and the entire input string. + */ + public JSONException syntaxError(String message) { + return new JSONException(message + this); } + /** + * Returns the current position and the entire input string. + */ @Override public String toString() { // consistent with the original implementation return " at character " + pos + " of " + in; @@ -395,14 +438,26 @@ public class JSONTokener { * implementation and may be used by some clients. */ + /** + * Returns true until the input has been exhausted. + */ public boolean more() { return pos < in.length(); } + /** + * Returns the next available character, or the null character '\0' if all + * input has been exhausted. The return value of this method is ambiguous + * for JSON strings that contain the character '\0'. + */ public char next() { return pos < in.length() ? in.charAt(pos++) : '\0'; } + /** + * Returns the next available character if it equals {@code c}. Otherwise an + * exception is thrown. + */ public char next(char c) throws JSONException { char result = next(); if (result != c) { @@ -411,13 +466,27 @@ public class JSONTokener { return result; } + /** + * Returns the next character that is not whitespace and does not belong to + * a comment. If the input is exhausted before such a character can be + * found, the null character '\0' is returned. The return value of this + * method is ambiguous for JSON strings that contain the character '\0'. + */ public char nextClean() throws JSONException { int nextCleanInt = nextCleanInternal(); return nextCleanInt == -1 ? '\0' : (char) nextCleanInt; } /** - * TODO: note about how this method returns a substring, and could cause a memory leak + * Returns the next {@code length} characters of the input. + * + *

The returned string shares its backing character array with this + * tokener's input string. If a reference to the returned string may be held + * indefinitely, you should {@link String(String) copy} it first to avoid + * memory leaks. + * + * @throws JSONException if the remaining input is not long enough to + * satisfy this request. */ public String next(int length) throws JSONException { if (pos + length > in.length()) { @@ -429,7 +498,20 @@ public class JSONTokener { } /** - * TODO: note about how this method returns a substring, and could cause a memory leak + * Returns the {@link String#trim trimmed} string holding the characters up + * to but not including the first of: + *

+ * + *

The returned string shares its backing character array with this + * tokener's input string. If a reference to the returned string may be held + * indefinitely, you should {@link String(String) copy} it first to avoid + * memory leaks. + * + * @return a possibly-empty string */ public String nextTo(String excluded) { if (excluded == null) { @@ -439,33 +521,54 @@ public class JSONTokener { } /** - * TODO: note about how this method returns a substring, and could cause a memory leak + * Equivalent to {@code nextTo(String.valueOf(excluded))}. */ public String nextTo(char excluded) { return nextToInternal(String.valueOf(excluded)).trim(); } + /** + * Advances past all input up to and including the next occurrence of + * {@code thru}. If the remaining input doesn't contain {@code thru}, the + * input is exhausted. + */ public void skipPast(String thru) { int thruStart = in.indexOf(thru, pos); pos = thruStart == -1 ? in.length() : (thruStart + thru.length()); } + /** + * Advances past all input up to but not including the next occurrence of + * {@code to}. If the remaining input doesn't contain {@code to}, the input + * is unchanged. + */ public char skipTo(char to) { - for (int i = pos, length = in.length(); i < length; i++) { - if (in.charAt(i) == to) { - pos = i; - return to; - } + int index = in.indexOf(to, pos); + if (index != -1) { + pos = index; + return to; + } else { + return '\0'; } - return '\0'; } + /** + * Unreads the most recent character of input. If no input characters have + * been read, the input is unchanged. + */ public void back() { if (--pos == -1) { pos = 0; } } + /** + * Returns the integer [0..15] value for the given hex character, or -1 + * for non-hex input. + * + * @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other + * character will yield a -1 result. + */ public static int dehexchar(char hex) { if (hex >= '0' && hex <= '9') { return hex - '0'; -- 2.11.0