/** Returns a new instance that writes UTF-8 encoded JSON to {@code sink}. */ public static JsonWriter of(BufferedSink sink) { return new JsonUtf8Writer(sink); }
private void writeDeferredName() throws IOException { if (deferredName != null) { beforeName(); string(sink, deferredName); deferredName = null; } }
@Override public JsonWriter value(String value) throws IOException { if (value == null) { return nullValue(); } if (promoteValueToName) { return name(value); } writeDeferredName(); beforeValue(); string(sink, value); pathIndices[stackSize - 1]++; return this; }
@Override public JsonWriter beginObject() throws IOException { writeDeferredName(); return open(EMPTY_OBJECT, "{"); }
@Override public JsonWriter value(long value) throws IOException { if (promoteValueToName) { return name(Long.toString(value)); } writeDeferredName(); beforeValue(); sink.writeUtf8(Long.toString(value)); pathIndices[stackSize - 1]++; return this; }
/** * Inserts any necessary separators and whitespace before a name. Also * adjusts the stack to expect the name's value. */ private void beforeName() throws IOException { int context = peekScope(); if (context == NONEMPTY_OBJECT) { // first in object sink.writeByte(','); } else if (context != EMPTY_OBJECT) { // not in an object! throw new IllegalStateException("Nesting problem."); } newline(); replaceTop(DANGLING_NAME); }
@Override public JsonWriter value(boolean value) throws IOException { writeDeferredName(); beforeValue(); sink.writeUtf8(value ? "true" : "false"); pathIndices[stackSize - 1]++; return this; }
/** * Enters a new scope by appending any necessary whitespace and the given * bracket. */ private JsonWriter open(int empty, String openBracket) throws IOException { beforeValue(); pushScope(empty); pathIndices[stackSize - 1] = 0; sink.writeUtf8(openBracket); return this; }
/** * Closes the current scope by appending any necessary whitespace and the * given bracket. */ private JsonWriter close(int empty, int nonempty, String closeBracket) throws IOException { int context = peekScope(); if (context != nonempty && context != empty) { throw new IllegalStateException("Nesting problem."); } if (deferredName != null) { throw new IllegalStateException("Dangling name: " + deferredName); } stackSize--; pathNames[stackSize] = null; // Free the last path name so that it can be garbage collected! pathIndices[stackSize - 1]++; if (context == nonempty) { newline(); } sink.writeUtf8(closeBracket); return this; }
@Override public JsonWriter endObject() throws IOException { promoteValueToName = false; return close(EMPTY_OBJECT, NONEMPTY_OBJECT, "}"); }
JsonUtf8Writer(BufferedSink sink) { if (sink == null) { throw new NullPointerException("sink == null"); } this.sink = sink; pushScope(EMPTY_DOCUMENT); }
@Override public JsonWriter value(double value) throws IOException { if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } if (promoteValueToName) { return name(Double.toString(value)); } writeDeferredName(); beforeValue(); sink.writeUtf8(Double.toString(value)); pathIndices[stackSize - 1]++; return this; }
switch (peekScope()) { case NONEMPTY_DOCUMENT: if (!lenient) { replaceTop(NONEMPTY_DOCUMENT); break; replaceTop(NONEMPTY_ARRAY); newline(); break; newline(); break; replaceTop(NONEMPTY_OBJECT); break;
@Override public JsonWriter nullValue() throws IOException { if (deferredName != null) { if (serializeNulls) { writeDeferredName(); } else { deferredName = null; return this; // skip the name and the value } } beforeValue(); sink.writeUtf8("null"); pathIndices[stackSize - 1]++; return this; }
@Override public JsonWriter beginArray() throws IOException { writeDeferredName(); return open(EMPTY_ARRAY, "["); }
/** * Enters a new scope by appending any necessary whitespace and the given * bracket. */ private JsonWriter open(int empty, String openBracket) throws IOException { beforeValue(); pushScope(empty); pathIndices[stackSize - 1] = 0; sink.writeUtf8(openBracket); return this; }
/** * Closes the current scope by appending any necessary whitespace and the * given bracket. */ private JsonWriter close(int empty, int nonempty, String closeBracket) throws IOException { int context = peekScope(); if (context != nonempty && context != empty) { throw new IllegalStateException("Nesting problem."); } if (deferredName != null) { throw new IllegalStateException("Dangling name: " + deferredName); } stackSize--; pathNames[stackSize] = null; // Free the last path name so that it can be garbage collected! pathIndices[stackSize - 1]++; if (context == nonempty) { newline(); } sink.writeUtf8(closeBracket); return this; }
@Override public JsonWriter endArray() throws IOException { return close(EMPTY_ARRAY, NONEMPTY_ARRAY, "]"); }