Permit multiple top-level values in JsonWriter in lenient mode. Also fix some cases where we don't throw the right thing on a closed JsonWriter.
I'd prefer to not support multiple top-level values, but we support it in JsonReader and it's easier to be consistent. Kevin Hayen's patch pointed me in the right direction here, but I needed to do more work to cover some of the edge cases. Fixes issue 397.
This commit is contained in:
parent
5c978948a0
commit
2c8bec27d4
@ -314,7 +314,11 @@ public class JsonWriter implements Closeable {
|
||||
* Returns the value on the top of the stack.
|
||||
*/
|
||||
private JsonScope peek() {
|
||||
return stack.get(stack.size() - 1);
|
||||
int size = stack.size();
|
||||
if (size == 0) {
|
||||
throw new IllegalStateException("JsonWriter is closed.");
|
||||
}
|
||||
return stack.get(size - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -337,6 +341,9 @@ public class JsonWriter implements Closeable {
|
||||
if (deferredName != null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
throw new IllegalStateException("JsonWriter is closed.");
|
||||
}
|
||||
deferredName = name;
|
||||
return this;
|
||||
}
|
||||
@ -453,6 +460,9 @@ public class JsonWriter implements Closeable {
|
||||
* and flushes that writer.
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if (stack.isEmpty()) {
|
||||
throw new IllegalStateException("JsonWriter is closed.");
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@ -464,9 +474,11 @@ public class JsonWriter implements Closeable {
|
||||
public void close() throws IOException {
|
||||
out.close();
|
||||
|
||||
if (peek() != JsonScope.NONEMPTY_DOCUMENT) {
|
||||
int size = stack.size();
|
||||
if (size > 1 || size == 1 && stack.get(size - 1) != JsonScope.NONEMPTY_DOCUMENT) {
|
||||
throw new IOException("Incomplete document");
|
||||
}
|
||||
stack.clear();
|
||||
}
|
||||
|
||||
private void string(String value) throws IOException {
|
||||
@ -574,8 +586,15 @@ public class JsonWriter implements Closeable {
|
||||
* @param root true if the value is a new array or object, the two values
|
||||
* permitted as top-level elements.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
private void beforeValue(boolean root) throws IOException {
|
||||
switch (peek()) {
|
||||
case NONEMPTY_DOCUMENT:
|
||||
if (!lenient) {
|
||||
throw new IllegalStateException(
|
||||
"JSON must have only one top-level value.");
|
||||
}
|
||||
// fall-through
|
||||
case EMPTY_DOCUMENT: // first in document
|
||||
if (!lenient && !root) {
|
||||
throw new IllegalStateException(
|
||||
@ -599,10 +618,6 @@ public class JsonWriter implements Closeable {
|
||||
replaceTop(JsonScope.NONEMPTY_OBJECT);
|
||||
break;
|
||||
|
||||
case NONEMPTY_DOCUMENT:
|
||||
throw new IllegalStateException(
|
||||
"JSON must have only one top-level value.");
|
||||
|
||||
default:
|
||||
throw new IllegalStateException("Nesting problem: " + stack);
|
||||
}
|
||||
|
@ -16,12 +16,11 @@
|
||||
|
||||
package com.google.gson.stream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public final class JsonWriterTest extends TestCase {
|
||||
|
||||
@ -464,4 +463,104 @@ public final class JsonWriterTest extends TestCase {
|
||||
+ "]";
|
||||
assertEquals(expected, stringWriter.toString());
|
||||
}
|
||||
|
||||
public void testLenientWriterPermitsMultipleTopLevelValues() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.setLenient(true);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
assertEquals("[][]", stringWriter.toString());
|
||||
}
|
||||
|
||||
public void testStrictWriterDoesNotPermitMultipleTopLevelValues() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
try {
|
||||
writer.beginArray();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClosedWriterThrowsOnStructure() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
try {
|
||||
writer.beginArray();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
try {
|
||||
writer.endArray();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
try {
|
||||
writer.beginObject();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
try {
|
||||
writer.endObject();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClosedWriterThrowsOnName() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
try {
|
||||
writer.name("a");
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClosedWriterThrowsOnValue() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
try {
|
||||
writer.value("a");
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testClosedWriterThrowsOnFlush() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
try {
|
||||
writer.flush();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testWriterCloseIsIdempotent() throws IOException {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
JsonWriter writer = new JsonWriter(stringWriter);
|
||||
writer.beginArray();
|
||||
writer.endArray();
|
||||
writer.close();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user