/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
// 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:<pre> * JSONObject object = ... * String json = object.toString();</pre> * * <p>Stringers only encode well-formed JSON strings. In particular: * <ul> * <li>The stringer must have exactly one top-level array or object. * <li>Lexical scopes must be balanced: every call to {@link #array} must * have a matching call to {@link #endArray} and every call to {@link * #object} must have a matching call to {@link #endObject}. * <li>Arrays may not contain keys (property names). * <li>Objects must alternate keys (property names) and values. * <li>Values are inserted with either literal {@link #value(Object) value} * calls, or by nesting arrays or objects. * </ul> * Calls that would result in a malformed JSON string will fail with a * {@link JSONException}. * * <p>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)}. * * <p>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}. * * <p>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 overrideable methods is not specified. See <i>Effective Java</i> * Item 17, "Design and Document or inheritance or else prohibit it" for further * information.
*/ publicclass JSONStringer {
/** * The output data, containing at most one top-level array or object.
*/ final StringBuilder out = new StringBuilder();
/** * Lexical scoping elements within this stringer, necessary to insert the * appropriate separator characters (ie. commas and colons) and to detect * nesting errors.
*/ enum Scope {
/** * An array with no elements requires no separators or newlines before * it is closed.
*/
EMPTY_ARRAY,
/** * A array with at least one value requires a comma and newline before * the next element.
*/
NONEMPTY_ARRAY,
/** * An object with no keys or values requires no separators or newlines * before it is closed.
*/
EMPTY_OBJECT,
/** * An object whose most recent element is a key. The next element must * be a value.
*/
DANGLING_KEY,
/** * An object with at least one name/value pair requires a comma and * newline before the next element.
*/
NONEMPTY_OBJECT,
/** * A special bracketless array needed by JSONStringer.join() and * JSONObject.quote() only. Not used for JSON encoding.
*/ NULL,
}
/** * Unlike the original implementation, this stack isn't limited to 20 * levels of nesting.
*/ privatefinal List<Scope> stack = new ArrayList<Scope>();
/** * A string containing a full set of spaces for a single level of * indentation, or null for no pretty printing.
*/ privatefinal String indent;
/** * 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, "}");
}
/** * Enters a new scope by appending any necessary whitespace and the given * bracket.
*/
JSONStringer open(Scope empty, String openBracket) throws JSONException { if (stack.isEmpty() && out.length() > 0) { thrownew JSONException("Nesting problem: multiple top-level roots");
}
beforeValue();
stack.add(empty);
out.append(openBracket); returnthis;
}
/** * Closes the current scope by appending any necessary whitespace and the * given bracket.
*/
JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException {
Scope context = peek(); if (context != nonempty && context != empty) { thrownew JSONException("Nesting problem");
}
/** * Returns the value on the top of the stack.
*/ private Scope peek() throws JSONException { if (stack.isEmpty()) { thrownew JSONException("Nesting problem");
} return stack.get(stack.size() - 1);
}
/** * Replace the value on the top of the stack with the given value.
*/ privatevoid replaceTop(Scope topOfStack) {
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()) { thrownew JSONException("Nesting problem");
}
if (value instanceof JSONArray) {
((JSONArray) value).writeTo(this); returnthis;
/** * Encodes {@code value} to this stringer. * * @return this stringer.
*/ public JSONStringer value(boolean value) throws JSONException { if (stack.isEmpty()) { thrownew JSONException("Nesting problem");
}
beforeValue();
out.append(value); returnthis;
}
/** * 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()) { thrownew JSONException("Nesting problem");
}
beforeValue();
out.append(JSONObject.numberToString(value)); returnthis;
}
/** * Encodes {@code value} to this stringer. * * @return this stringer.
*/ public JSONStringer value(long value) throws JSONException { if (stack.isEmpty()) { thrownew JSONException("Nesting problem");
}
beforeValue();
out.append(value); returnthis;
}
privatevoid string(String value) {
out.append("\""); for (int i = 0, length = value.length(); i < length; i++) { char c = value.charAt(i);
/* * From RFC 4627, "All Unicode characters may be placed within the * quotation marks except for the characters that must be escaped: * quotation mark, reverse solidus, and the control characters * (U+0000 through U+001F)."
*/ switch (c) { case'"': case'\\': case'/':
out.append('\\').append(c); break;
privatevoid newline() { if (indent == null) { return;
}
out.append("\n"); for (int i = 0; i < stack.size(); i++) {
out.append(indent);
}
}
/** * 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) { thrownew JSONException("Names must be non-null");
}
beforeKey();
string(name); returnthis;
}
/** * Inserts any necessary separators and whitespace before a name. Also * adjusts the stack to expect the key's value.
*/ privatevoid beforeKey() throws JSONException {
Scope context = peek(); if (context == Scope.NONEMPTY_OBJECT) { // first in object
out.append(',');
} elseif (context != Scope.EMPTY_OBJECT) { // not in an object! thrownew JSONException("Nesting problem");
}
newline();
replaceTop(Scope.DANGLING_KEY);
}
/** * Inserts any necessary separators and whitespace before a literal value, * inline array, or inline object. Also adjusts the stack to expect either a * closing bracket or another element.
*/ privatevoid beforeValue() throws JSONException { if (stack.isEmpty()) { return;
}
Scope context = peek(); if (context == Scope.EMPTY_ARRAY) { // first in array
replaceTop(Scope.NONEMPTY_ARRAY);
newline();
} elseif (context == Scope.NONEMPTY_ARRAY) { // another in array
out.append(',');
newline();
} elseif (context == Scope.DANGLING_KEY) { // value for key
out.append(indent == null ? ":" : ": ");
replaceTop(Scope.NONEMPTY_OBJECT);
} elseif (context != Scope.NULL) { thrownew JSONException("Nesting problem");
}
}
/** * Returns the encoded JSON string. * * <p>If invoked with unterminated arrays or unclosed objects, this method's * return value is undefined. * * <p><strong>Warning:</strong> 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();
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-04-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.