Merge branch '1.5.x'
This commit is contained in:
commit
f2d3f51f3f
|
@ -17,100 +17,114 @@
|
||||||
package org.springframework.boot.configurationprocessor.json;
|
package org.springframework.boot.configurationprocessor.json;
|
||||||
|
|
||||||
class JSON {
|
class JSON {
|
||||||
/**
|
/**
|
||||||
* Returns the input if it is a JSON-permissible value; throws otherwise.
|
* Returns the input if it is a JSON-permissible value; throws otherwise.
|
||||||
*/
|
*/
|
||||||
static double checkDouble(double d) throws JSONException {
|
static double checkDouble(double d) throws JSONException {
|
||||||
if (Double.isInfinite(d) || Double.isNaN(d)) {
|
if (Double.isInfinite(d) || Double.isNaN(d)) {
|
||||||
throw new JSONException("Forbidden numeric value: " + d);
|
throw new JSONException("Forbidden numeric value: " + d);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Boolean toBoolean(Object value) {
|
static Boolean toBoolean(Object value) {
|
||||||
if (value instanceof Boolean) {
|
if (value instanceof Boolean) {
|
||||||
return (Boolean) value;
|
return (Boolean) value;
|
||||||
} else if (value instanceof String) {
|
}
|
||||||
String stringValue = (String) value;
|
else if (value instanceof String) {
|
||||||
if ("true".equalsIgnoreCase(stringValue)) {
|
String stringValue = (String) value;
|
||||||
return true;
|
if ("true".equalsIgnoreCase(stringValue)) {
|
||||||
} else if ("false".equalsIgnoreCase(stringValue)) {
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
else if ("false".equalsIgnoreCase(stringValue)) {
|
||||||
}
|
return false;
|
||||||
return null;
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static Double toDouble(Object value) {
|
static Double toDouble(Object value) {
|
||||||
if (value instanceof Double) {
|
if (value instanceof Double) {
|
||||||
return (Double) value;
|
return (Double) value;
|
||||||
} else if (value instanceof Number) {
|
}
|
||||||
return ((Number) value).doubleValue();
|
else if (value instanceof Number) {
|
||||||
} else if (value instanceof String) {
|
return ((Number) value).doubleValue();
|
||||||
try {
|
}
|
||||||
return Double.valueOf((String) value);
|
else if (value instanceof String) {
|
||||||
} catch (NumberFormatException ignored) {
|
try {
|
||||||
}
|
return Double.valueOf((String) value);
|
||||||
}
|
}
|
||||||
return null;
|
catch (NumberFormatException ignored) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static Integer toInteger(Object value) {
|
static Integer toInteger(Object value) {
|
||||||
if (value instanceof Integer) {
|
if (value instanceof Integer) {
|
||||||
return (Integer) value;
|
return (Integer) value;
|
||||||
} else if (value instanceof Number) {
|
}
|
||||||
return ((Number) value).intValue();
|
else if (value instanceof Number) {
|
||||||
} else if (value instanceof String) {
|
return ((Number) value).intValue();
|
||||||
try {
|
}
|
||||||
return (int) Double.parseDouble((String) value);
|
else if (value instanceof String) {
|
||||||
} catch (NumberFormatException ignored) {
|
try {
|
||||||
}
|
return (int) Double.parseDouble((String) value);
|
||||||
}
|
}
|
||||||
return null;
|
catch (NumberFormatException ignored) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static Long toLong(Object value) {
|
static Long toLong(Object value) {
|
||||||
if (value instanceof Long) {
|
if (value instanceof Long) {
|
||||||
return (Long) value;
|
return (Long) value;
|
||||||
} else if (value instanceof Number) {
|
}
|
||||||
return ((Number) value).longValue();
|
else if (value instanceof Number) {
|
||||||
} else if (value instanceof String) {
|
return ((Number) value).longValue();
|
||||||
try {
|
}
|
||||||
return (long) Double.parseDouble((String) value);
|
else if (value instanceof String) {
|
||||||
} catch (NumberFormatException ignored) {
|
try {
|
||||||
}
|
return (long) Double.parseDouble((String) value);
|
||||||
}
|
}
|
||||||
return null;
|
catch (NumberFormatException ignored) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static String toString(Object value) {
|
static String toString(Object value) {
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
return (String) value;
|
return (String) value;
|
||||||
} else if (value != null) {
|
}
|
||||||
return String.valueOf(value);
|
else if (value != null) {
|
||||||
}
|
return String.valueOf(value);
|
||||||
return null;
|
}
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static JSONException typeMismatch(Object indexOrName, Object actual,
|
public static JSONException typeMismatch(Object indexOrName, Object actual,
|
||||||
String requiredType) throws JSONException {
|
String requiredType) throws JSONException {
|
||||||
if (actual == null) {
|
if (actual == null) {
|
||||||
throw new JSONException("Value at " + indexOrName + " is null.");
|
throw new JSONException("Value at " + indexOrName + " is null.");
|
||||||
} else {
|
}
|
||||||
throw new JSONException("Value " + actual + " at " + indexOrName
|
else {
|
||||||
+ " of type " + actual.getClass().getName()
|
throw new JSONException("Value " + actual + " at " + indexOrName
|
||||||
+ " cannot be converted to " + requiredType);
|
+ " of type " + actual.getClass().getName()
|
||||||
}
|
+ " cannot be converted to " + requiredType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static JSONException typeMismatch(Object actual, String requiredType)
|
public static JSONException typeMismatch(Object actual, String requiredType)
|
||||||
throws JSONException {
|
throws JSONException {
|
||||||
if (actual == null) {
|
if (actual == null) {
|
||||||
throw new JSONException("Value is null.");
|
throw new JSONException("Value is null.");
|
||||||
} else {
|
}
|
||||||
throw new JSONException("Value " + actual
|
else {
|
||||||
+ " of type " + actual.getClass().getName()
|
throw new JSONException("Value " + actual
|
||||||
+ " cannot be converted to " + requiredType);
|
+ " of type " + actual.getClass().getName()
|
||||||
}
|
+ " cannot be converted to " + requiredType);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,7 +43,7 @@ package org.springframework.boot.configurationprocessor.json;
|
||||||
*/
|
*/
|
||||||
public class JSONException extends Exception {
|
public class JSONException extends Exception {
|
||||||
|
|
||||||
public JSONException(String s) {
|
public JSONException(String s) {
|
||||||
super(s);
|
super(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2018 the original author or authors.
|
* Copyright (C) 2010 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -20,7 +20,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
// Note: this class was written without inspecting the non-free org.json source code.
|
// Note: this class was written without inspecting the non-free org.json sourcecode.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most
|
* Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most
|
||||||
|
@ -60,373 +60,407 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class JSONStringer {
|
public class JSONStringer {
|
||||||
|
|
||||||
/** The output data, containing at most one top-level array or object. */
|
/** The output data, containing at most one top-level array or object. */
|
||||||
final StringBuilder out = new StringBuilder();
|
final StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lexical scoping elements within this stringer, necessary to insert the
|
* Lexical scoping elements within this stringer, necessary to insert the
|
||||||
* appropriate separator characters (ie. commas and colons) and to detect
|
* appropriate separator characters (ie. commas and colons) and to detect
|
||||||
* nesting errors.
|
* nesting errors.
|
||||||
*/
|
*/
|
||||||
enum Scope {
|
enum Scope {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array with no elements requires no separators or newlines before
|
* An array with no elements requires no separators or newlines before
|
||||||
* it is closed.
|
* it is closed.
|
||||||
*/
|
*/
|
||||||
EMPTY_ARRAY,
|
EMPTY_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A array with at least one value requires a comma and newline before
|
* A array with at least one value requires a comma and newline before
|
||||||
* the next element.
|
* the next element.
|
||||||
*/
|
*/
|
||||||
NONEMPTY_ARRAY,
|
NONEMPTY_ARRAY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object with no keys or values requires no separators or newlines
|
* An object with no keys or values requires no separators or newlines
|
||||||
* before it is closed.
|
* before it is closed.
|
||||||
*/
|
*/
|
||||||
EMPTY_OBJECT,
|
EMPTY_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object whose most recent element is a key. The next element must
|
* An object whose most recent element is a key. The next element must
|
||||||
* be a value.
|
* be a value.
|
||||||
*/
|
*/
|
||||||
DANGLING_KEY,
|
DANGLING_KEY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object with at least one name/value pair requires a comma and
|
* An object with at least one name/value pair requires a comma and
|
||||||
* newline before the next element.
|
* newline before the next element.
|
||||||
*/
|
*/
|
||||||
NONEMPTY_OBJECT,
|
NONEMPTY_OBJECT,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A special bracketless array needed by JSONStringer.join() and
|
* A special bracketless array needed by JSONStringer.join() and
|
||||||
* JSONObject.quote() only. Not used for JSON encoding.
|
* JSONObject.quote() only. Not used for JSON encoding.
|
||||||
*/
|
*/
|
||||||
NULL
|
NULL,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlike the original implementation, this stack isn't limited to 20
|
* Unlike the original implementation, this stack isn't limited to 20
|
||||||
* levels of nesting.
|
* levels of nesting.
|
||||||
*/
|
*/
|
||||||
private final List<Scope> stack = new ArrayList<Scope>();
|
private final List<Scope> stack = new ArrayList<Scope>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string containing a full set of spaces for a single level of
|
* A string containing a full set of spaces for a single level of
|
||||||
* indentation, or null for no pretty printing.
|
* indentation, or null for no pretty printing.
|
||||||
*/
|
*/
|
||||||
private final String indent;
|
private final String indent;
|
||||||
|
|
||||||
public JSONStringer() {
|
public JSONStringer() {
|
||||||
indent = null;
|
this.indent = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONStringer(int indentSpaces) {
|
JSONStringer(int indentSpaces) {
|
||||||
char[] indentChars = new char[indentSpaces];
|
char[] indentChars = new char[indentSpaces];
|
||||||
Arrays.fill(indentChars, ' ');
|
Arrays.fill(indentChars, ' ');
|
||||||
indent = new String(indentChars);
|
this.indent = new String(indentChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begins encoding a new array. Each call to this method must be paired with
|
* Begins encoding a new array. Each call to this method must be paired with
|
||||||
* a call to {@link #endArray}.
|
* a call to {@link #endArray}.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer array() throws JSONException {
|
*/
|
||||||
return open(Scope.EMPTY_ARRAY, "[");
|
public JSONStringer array() throws JSONException {
|
||||||
}
|
return open(Scope.EMPTY_ARRAY, "[");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends encoding the current array.
|
* Ends encoding the current array.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer endArray() throws JSONException {
|
*/
|
||||||
return close(Scope.EMPTY_ARRAY, Scope.NONEMPTY_ARRAY, "]");
|
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
|
* Begins encoding a new object. Each call to this method must be paired
|
||||||
* with a call to {@link #endObject}.
|
* with a call to {@link #endObject}.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer object() throws JSONException {
|
*/
|
||||||
return open(Scope.EMPTY_OBJECT, "{");
|
public JSONStringer object() throws JSONException {
|
||||||
}
|
return open(Scope.EMPTY_OBJECT, "{");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends encoding the current object.
|
* Ends encoding the current object.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer endObject() throws JSONException {
|
*/
|
||||||
return close(Scope.EMPTY_OBJECT, Scope.NONEMPTY_OBJECT, "}");
|
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
|
* Enters a new scope by appending any necessary whitespace and the given
|
||||||
* bracket.
|
* bracket.
|
||||||
*/
|
* @param empty any necessary whitespace
|
||||||
JSONStringer open(Scope empty, String openBracket) throws JSONException {
|
* @param openBracket the open bracket
|
||||||
if (stack.isEmpty() && out.length() > 0) {
|
* @return this object
|
||||||
throw new JSONException("Nesting problem: multiple top-level roots");
|
* @throws JSONException if processing of json failed
|
||||||
}
|
*/
|
||||||
beforeValue();
|
JSONStringer open(Scope empty, String openBracket) throws JSONException {
|
||||||
stack.add(empty);
|
if (this.stack.isEmpty() && this.out.length() > 0) {
|
||||||
out.append(openBracket);
|
throw new JSONException("Nesting problem: multiple top-level roots");
|
||||||
return this;
|
}
|
||||||
}
|
beforeValue();
|
||||||
|
this.stack.add(empty);
|
||||||
|
this.out.append(openBracket);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the current scope by appending any necessary whitespace and the
|
* Closes the current scope by appending any necessary whitespace and the
|
||||||
* given bracket.
|
* given bracket.
|
||||||
*/
|
* @param empty any necessary whitespace
|
||||||
JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException {
|
* @param nonempty the current scope
|
||||||
Scope context = peek();
|
* @param closeBracket the close bracket
|
||||||
if (context != nonempty && context != empty) {
|
* @throws JSONException if processing of json failed
|
||||||
throw new JSONException("Nesting problem");
|
*/
|
||||||
}
|
JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException {
|
||||||
|
Scope context = peek();
|
||||||
|
if (context != nonempty && context != empty) {
|
||||||
|
throw new JSONException("Nesting problem");
|
||||||
|
}
|
||||||
|
|
||||||
stack.remove(stack.size() - 1);
|
this.stack.remove(this.stack.size() - 1);
|
||||||
if (context == nonempty) {
|
if (context == nonempty) {
|
||||||
newline();
|
newline();
|
||||||
}
|
}
|
||||||
out.append(closeBracket);
|
this.out.append(closeBracket);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value on the top of the stack.
|
* Returns the value on the top of the stack.
|
||||||
*/
|
* @return the scope
|
||||||
private Scope peek() throws JSONException {
|
* @throws JSONException if processing of json failed
|
||||||
if (stack.isEmpty()) {
|
*/
|
||||||
throw new JSONException("Nesting problem");
|
private Scope peek() throws JSONException {
|
||||||
}
|
if (this.stack.isEmpty()) {
|
||||||
return stack.get(stack.size() - 1);
|
throw new JSONException("Nesting problem");
|
||||||
}
|
}
|
||||||
|
return this.stack.get(this.stack.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace the value on the top of the stack with the given value.
|
* Replace the value on the top of the stack with the given value.
|
||||||
*/
|
* @param topOfStack the scope at the top of the stack
|
||||||
private void replaceTop(Scope topOfStack) {
|
*/
|
||||||
stack.set(stack.size() - 1, topOfStack);
|
private void replaceTop(Scope topOfStack) {
|
||||||
}
|
this.stack.set(this.stack.size() - 1, topOfStack);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes {@code value}.
|
* Encodes {@code value}.
|
||||||
*
|
*
|
||||||
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
|
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
|
||||||
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
|
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
|
||||||
* or {@link Double#isInfinite() infinities}.
|
* or {@link Double#isInfinite() infinities}.
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer value(Object value) throws JSONException {
|
*/
|
||||||
if (stack.isEmpty()) {
|
public JSONStringer value(Object value) throws JSONException {
|
||||||
throw new JSONException("Nesting problem");
|
if (this.stack.isEmpty()) {
|
||||||
}
|
throw new JSONException("Nesting problem");
|
||||||
|
}
|
||||||
|
|
||||||
if (value instanceof JSONArray) {
|
if (value instanceof JSONArray) {
|
||||||
((JSONArray) value).writeTo(this);
|
((JSONArray) value).writeTo(this);
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
} else if (value instanceof JSONObject) {
|
}
|
||||||
((JSONObject) value).writeTo(this);
|
else if (value instanceof JSONObject) {
|
||||||
return this;
|
((JSONObject) value).writeTo(this);
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
beforeValue();
|
beforeValue();
|
||||||
|
|
||||||
if (value == null
|
if (value == null
|
||||||
|| value instanceof Boolean
|
|| value instanceof Boolean
|
||||||
|| value == JSONObject.NULL) {
|
|| value == JSONObject.NULL) {
|
||||||
out.append(value);
|
this.out.append(value);
|
||||||
|
|
||||||
} else if (value instanceof Number) {
|
}
|
||||||
out.append(JSONObject.numberToString((Number) value));
|
else if (value instanceof Number) {
|
||||||
|
this.out.append(JSONObject.numberToString((Number) value));
|
||||||
|
|
||||||
} else {
|
}
|
||||||
string(value.toString());
|
else {
|
||||||
}
|
string(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes {@code value} to this stringer.
|
* Encodes {@code value} to this stringer.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @param value the value to encode
|
||||||
*/
|
* @return this stringer.
|
||||||
public JSONStringer value(boolean value) throws JSONException {
|
* @throws JSONException if processing of json failed
|
||||||
if (stack.isEmpty()) {
|
*/
|
||||||
throw new JSONException("Nesting problem");
|
public JSONStringer value(boolean value) throws JSONException {
|
||||||
}
|
if (this.stack.isEmpty()) {
|
||||||
beforeValue();
|
throw new JSONException("Nesting problem");
|
||||||
out.append(value);
|
}
|
||||||
return this;
|
beforeValue();
|
||||||
}
|
this.out.append(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes {@code value} to this stringer.
|
* Encodes {@code value} to this stringer.
|
||||||
*
|
*
|
||||||
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
|
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
|
||||||
* {@link Double#isInfinite() infinities}.
|
* {@link Double#isInfinite() infinities}.
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer value(double value) throws JSONException {
|
*/
|
||||||
if (stack.isEmpty()) {
|
public JSONStringer value(double value) throws JSONException {
|
||||||
throw new JSONException("Nesting problem");
|
if (this.stack.isEmpty()) {
|
||||||
}
|
throw new JSONException("Nesting problem");
|
||||||
beforeValue();
|
}
|
||||||
out.append(JSONObject.numberToString(value));
|
beforeValue();
|
||||||
return this;
|
this.out.append(JSONObject.numberToString(value));
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes {@code value} to this stringer.
|
* Encodes {@code value} to this stringer.
|
||||||
*
|
*
|
||||||
* @return this stringer.
|
* @param value the value to encode
|
||||||
*/
|
* @return this stringer.
|
||||||
public JSONStringer value(long value) throws JSONException {
|
* @throws JSONException if processing of json failed
|
||||||
if (stack.isEmpty()) {
|
*/
|
||||||
throw new JSONException("Nesting problem");
|
public JSONStringer value(long value) throws JSONException {
|
||||||
}
|
if (this.stack.isEmpty()) {
|
||||||
beforeValue();
|
throw new JSONException("Nesting problem");
|
||||||
out.append(value);
|
}
|
||||||
return this;
|
beforeValue();
|
||||||
}
|
this.out.append(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private void string(String value) {
|
private void string(String value) {
|
||||||
out.append("\"");
|
this.out.append("\"");
|
||||||
for (int i = 0, length = value.length(); i < length; i++) {
|
for (int i = 0, length = value.length(); i < length; i++) {
|
||||||
char c = value.charAt(i);
|
char c = value.charAt(i);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From RFC 4627, "All Unicode characters may be placed within the
|
* From RFC 4627, "All Unicode characters may be placed within the
|
||||||
* quotation marks except for the characters that must be escaped:
|
* quotation marks except for the characters that must be escaped:
|
||||||
* quotation mark, reverse solidus, and the control characters
|
* quotation mark, reverse solidus, and the control characters
|
||||||
* (U+0000 through U+001F)."
|
* (U+0000 through U+001F)."
|
||||||
*/
|
*/
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '"':
|
case '"':
|
||||||
case '\\':
|
case '\\':
|
||||||
case '/':
|
case '/':
|
||||||
out.append('\\').append(c);
|
this.out.append('\\').append(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
out.append("\\t");
|
this.out.append("\\t");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\b':
|
case '\b':
|
||||||
out.append("\\b");
|
this.out.append("\\b");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
out.append("\\n");
|
this.out.append("\\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\r':
|
case '\r':
|
||||||
out.append("\\r");
|
this.out.append("\\r");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\f':
|
case '\f':
|
||||||
out.append("\\f");
|
this.out.append("\\f");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (c <= 0x1F) {
|
if (c <= 0x1F) {
|
||||||
out.append(String.format("\\u%04x", (int) c));
|
this.out.append(String.format("\\u%04x", (int) c));
|
||||||
} else {
|
}
|
||||||
out.append(c);
|
else {
|
||||||
}
|
this.out.append(c);
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
out.append("\"");
|
this.out.append("\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void newline() {
|
private void newline() {
|
||||||
if (indent == null) {
|
if (this.indent == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.append("\n");
|
this.out.append("\n");
|
||||||
for (int i = 0; i < stack.size(); i++) {
|
for (int i = 0; i < this.stack.size(); i++) {
|
||||||
out.append(indent);
|
this.out.append(this.indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the key (property name) to this stringer.
|
* Encodes the key (property name) to this stringer.
|
||||||
*
|
*
|
||||||
* @param name the name of the forthcoming value. May not be null.
|
* @param name the name of the forthcoming value. May not be null.
|
||||||
* @return this stringer.
|
* @return this stringer.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
public JSONStringer key(String name) throws JSONException {
|
*/
|
||||||
if (name == null) {
|
public JSONStringer key(String name) throws JSONException {
|
||||||
throw new JSONException("Names must be non-null");
|
if (name == null) {
|
||||||
}
|
throw new JSONException("Names must be non-null");
|
||||||
beforeKey();
|
}
|
||||||
string(name);
|
beforeKey();
|
||||||
return this;
|
string(name);
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts any necessary separators and whitespace before a name. Also
|
* Inserts any necessary separators and whitespace before a name. Also
|
||||||
* adjusts the stack to expect the key's value.
|
* adjusts the stack to expect the key's value.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
private void beforeKey() throws JSONException {
|
*/
|
||||||
Scope context = peek();
|
private void beforeKey() throws JSONException {
|
||||||
if (context == Scope.NONEMPTY_OBJECT) { // first in object
|
Scope context = peek();
|
||||||
out.append(',');
|
if (context == Scope.NONEMPTY_OBJECT) { // first in object
|
||||||
} else if (context != Scope.EMPTY_OBJECT) { // not in an object!
|
this.out.append(',');
|
||||||
throw new JSONException("Nesting problem");
|
}
|
||||||
}
|
else if (context != Scope.EMPTY_OBJECT) { // not in an object!
|
||||||
newline();
|
throw new JSONException("Nesting problem");
|
||||||
replaceTop(Scope.DANGLING_KEY);
|
}
|
||||||
}
|
newline();
|
||||||
|
replaceTop(Scope.DANGLING_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts any necessary separators and whitespace before a literal value,
|
* Inserts any necessary separators and whitespace before a literal value,
|
||||||
* inline array, or inline object. Also adjusts the stack to expect either a
|
* inline array, or inline object. Also adjusts the stack to expect either a
|
||||||
* closing bracket or another element.
|
* closing bracket or another element.
|
||||||
*/
|
* @throws JSONException if processing of json failed
|
||||||
private void beforeValue() throws JSONException {
|
*/
|
||||||
if (stack.isEmpty()) {
|
private void beforeValue() throws JSONException {
|
||||||
return;
|
if (this.stack.isEmpty()) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Scope context = peek();
|
Scope context = peek();
|
||||||
if (context == Scope.EMPTY_ARRAY) { // first in array
|
if (context == Scope.EMPTY_ARRAY) { // first in array
|
||||||
replaceTop(Scope.NONEMPTY_ARRAY);
|
replaceTop(Scope.NONEMPTY_ARRAY);
|
||||||
newline();
|
newline();
|
||||||
} else if (context == Scope.NONEMPTY_ARRAY) { // another in array
|
}
|
||||||
out.append(',');
|
else if (context == Scope.NONEMPTY_ARRAY) { // another in array
|
||||||
newline();
|
this.out.append(',');
|
||||||
} else if (context == Scope.DANGLING_KEY) { // value for key
|
newline();
|
||||||
out.append(indent == null ? ":" : ": ");
|
}
|
||||||
replaceTop(Scope.NONEMPTY_OBJECT);
|
else if (context == Scope.DANGLING_KEY) { // value for key
|
||||||
} else if (context != Scope.NULL) {
|
this.out.append(this.indent == null ? ":" : ": ");
|
||||||
throw new JSONException("Nesting problem");
|
replaceTop(Scope.NONEMPTY_OBJECT);
|
||||||
}
|
}
|
||||||
}
|
else if (context != Scope.NULL) {
|
||||||
|
throw new JSONException("Nesting problem");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the encoded JSON string.
|
* Returns the encoded JSON string.
|
||||||
*
|
*
|
||||||
* <p>If invoked with unterminated arrays or unclosed objects, this method's
|
* <p>If invoked with unterminated arrays or unclosed objects, this method's
|
||||||
* return value is undefined.
|
* return value is undefined.
|
||||||
*
|
*
|
||||||
* <p><strong>Warning:</strong> although it contradicts the general contract
|
* <p><strong>Warning:</strong> although it contradicts the general contract
|
||||||
* of {@link Object#toString}, this method returns null if the stringer
|
* of {@link Object#toString}, this method returns null if the stringer
|
||||||
* contains no data.
|
* contains no data.
|
||||||
*/
|
* @return the encoded JSON string.
|
||||||
@Override public String toString() {
|
*/
|
||||||
return out.length() == 0 ? null : out.toString();
|
@Override
|
||||||
}
|
public String toString() {
|
||||||
|
return this.out.length() == 0 ? null : this.out.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue