/** * Encodes {@code data} as a JSON string. This applies quotes and any * necessary character escaping. * * @param data the string to encode. Null will be interpreted as an empty * string. * @return the quoted string. */ public static String quote(String data) { if (data == null) { return "\"\""; } try { JSONStringer stringer = new JSONStringer(); stringer.open(JSONStringer.Scope.NULL, ""); stringer.string(data); stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); return stringer.toString(); } catch (RuntimeException e) { throw new AssertionError(); } }
/** * 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. */ private void beforeValue(){ if (stack.isEmpty()) { return; } Scope context = peek(); if (context == Scope.EMPTY_ARRAY) { // first in array replaceTop(Scope.NONEMPTY_ARRAY); newline(); } else if (context == Scope.NONEMPTY_ARRAY) { // another in array out.append(','); newline(); } else if (context == Scope.DANGLING_KEY) { // value for key out.append(indent == null ? ":" : ": "); replaceTop(Scope.NONEMPTY_OBJECT); } else if (context != Scope.NULL) { throw new RuntimeException("Nesting problem"); } }
/** * Closes the current scope by appending any necessary whitespace and the * given bracket. */ JSONStringer close(Scope empty, Scope nonempty, String closeBracket){ Scope context = peek(); if (context != nonempty && context != empty) { throw new RuntimeException("Nesting problem"); } stack.remove(stack.size() - 1); if (context == nonempty) { newline(); } out.append(closeBracket); return this; }
/** * Enters a new scope by appending any necessary whitespace and the given * bracket. */ JSONStringer open(Scope empty, String openBracket){ if (stack.isEmpty() && out.length() > 0) { throw new RuntimeException("Nesting problem: multiple top-level roots"); } beforeValue(); stack.add(empty); out.append(openBracket); return this; }
/** * 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. */ private void beforeValue(){ if (stack.isEmpty()) { return; } Scope context = peek(); if (context == Scope.EMPTY_ARRAY) { // first in array replaceTop(Scope.NONEMPTY_ARRAY); newline(); } else if (context == Scope.NONEMPTY_ARRAY) { // another in array out.append(','); newline(); } else if (context == Scope.DANGLING_KEY) { // value for key out.append(indent == null ? ":" : ": "); replaceTop(Scope.NONEMPTY_OBJECT); } else if (context != Scope.NULL) { throw new RuntimeException("Nesting problem"); } }
/** * Closes the current scope by appending any necessary whitespace and the * given bracket. */ JSONStringer close(Scope empty, Scope nonempty, String closeBracket){ Scope context = peek(); if (context != nonempty && context != empty) { throw new RuntimeException("Nesting problem"); } stack.remove(stack.size() - 1); if (context == nonempty) { newline(); } out.append(closeBracket); return this; }
/** * Enters a new scope by appending any necessary whitespace and the given * bracket. */ JSONStringer open(Scope empty, String openBracket){ if (stack.isEmpty() && out.length() > 0) { throw new RuntimeException("Nesting problem: multiple top-level roots"); } beforeValue(); stack.add(empty); out.append(openBracket); return this; }
/** * Encodes {@code data} as a JSON string. This applies quotes and any * necessary character escaping. * * @param data the string to encode. Null will be interpreted as an empty * string. * @return the quoted string. */ public static String quote(String data) { if (data == null) { return "\"\""; } try { JSONStringer stringer = new JSONStringer(); stringer.open(JSONStringer.Scope.NULL, ""); stringer.string(data); stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); return stringer.toString(); } catch (RuntimeException e) { throw new AssertionError(); } }