diff --git a/moshi/src/main/java/com/squareup/moshi/JsonReader.java b/moshi/src/main/java/com/squareup/moshi/JsonReader.java
index e04acf9..29146a3 100644
--- a/moshi/src/main/java/com/squareup/moshi/JsonReader.java
+++ b/moshi/src/main/java/com/squareup/moshi/JsonReader.java
@@ -497,8 +497,7 @@ public abstract class JsonReader implements Closeable {
* jsonReader.nextInt() // Returns 456, reader contains 789 and ].
* }
*/
- // TODO(jwilson): make this public once it's supported in JsonUtf8Reader.
- abstract JsonReader peekJson();
+ public abstract JsonReader peekJson();
/**
* Returns a JsonPath to
diff --git a/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.java b/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.java
index 2703abe..571dde2 100644
--- a/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.java
+++ b/moshi/src/main/java/com/squareup/moshi/JsonUtf8Reader.java
@@ -98,6 +98,27 @@ final class JsonUtf8Reader extends JsonReader {
pushScope(JsonScope.EMPTY_DOCUMENT);
}
+ /** Copy-constructor makes a deep copy for peeking. */
+ JsonUtf8Reader(JsonUtf8Reader copyFrom) {
+ super(copyFrom);
+
+ BufferedSource sourcePeek = copyFrom.source.peek();
+ this.source = sourcePeek;
+ this.buffer = sourcePeek.getBuffer();
+ this.peeked = copyFrom.peeked;
+ this.peekedLong = copyFrom.peekedLong;
+ this.peekedNumberLength = copyFrom.peekedNumberLength;
+ this.peekedString = copyFrom.peekedString;
+
+ // Make sure our buffer has as many bytes as the source's buffer. This is necessary because
+ // JsonUtf8Reader assumes any data it has peeked (like the peekedNumberLength) are buffered.
+ try {
+ sourcePeek.require(copyFrom.buffer.size());
+ } catch (IOException e) {
+ throw new AssertionError();
+ }
+ }
+
@Override public void beginArray() throws IOException {
int p = peeked;
if (p == PEEKED_NONE) {
@@ -1051,8 +1072,8 @@ final class JsonUtf8Reader extends JsonReader {
return found;
}
- @Override JsonReader peekJson() {
- throw new UnsupportedOperationException("TODO");
+ @Override public JsonReader peekJson() {
+ return new JsonUtf8Reader(this);
}
@Override public String toString() {
diff --git a/moshi/src/main/java/com/squareup/moshi/JsonValueReader.java b/moshi/src/main/java/com/squareup/moshi/JsonValueReader.java
index 4246d3d..33f0eb3 100644
--- a/moshi/src/main/java/com/squareup/moshi/JsonValueReader.java
+++ b/moshi/src/main/java/com/squareup/moshi/JsonValueReader.java
@@ -318,7 +318,7 @@ final class JsonValueReader extends JsonReader {
}
}
- @Override JsonReader peekJson() {
+ @Override public JsonReader peekJson() {
return new JsonValueReader(this);
}
diff --git a/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java b/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java
index 8f5c045..95c1c40 100644
--- a/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java
+++ b/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java
@@ -33,6 +33,7 @@ import static com.squareup.moshi.JsonReader.Token.STRING;
import static com.squareup.moshi.TestUtil.repeat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@@ -988,7 +989,6 @@ public final class JsonReaderTest {
@Test public void basicPeekJson() throws IOException {
JsonReader reader = newReader("{\"a\":12,\"b\":[34,56],\"c\":78}");
- assumeTrue(reader instanceof JsonValueReader); // Not implemented for JsonUtf8Reader yet!
reader.beginObject();
assertThat(reader.nextName()).isEqualTo("a");
assertThat(reader.nextInt()).isEqualTo(12);
@@ -1021,7 +1021,6 @@ public final class JsonReaderTest {
*/
@Test public void peekJsonReader() throws IOException {
JsonReader reader = newReader("[12,34,{\"a\":56,\"b\":78},90]");
- assumeTrue(reader instanceof JsonValueReader); // Not implemented for JsonUtf8Reader yet!
for (int i = 0; i < 12; i++) {
readPeek12Steps(reader.peekJson(), i, 12);
readPeek12Steps(reader, i, i + 1);
@@ -1084,4 +1083,67 @@ public final class JsonReaderTest {
assertThat(reader.getPath()).isEqualTo("$");
}
}
+
+ /** Confirm that we can peek in every state of the UTF-8 reader. */
+ @Test public void peekAfterPeek() throws IOException {
+ JsonReader reader = newReader(
+ "[{\"a\":\"aaa\",'b':'bbb',c:c,\"d\":\"d\"},true,false,null,1,2.0]");
+ reader.setLenient(true);
+ readValue(reader, true);
+ reader.peekJson();
+ }
+
+ @Test public void peekAfterPromoteNameToValue() throws IOException {
+ JsonReader reader = newReader("{\"a\":\"b\"}");
+ reader.beginObject();
+ reader.promoteNameToValue();
+ assertEquals("a", reader.peekJson().nextString());
+ assertEquals("a", reader.nextString());
+ assertEquals("b", reader.peekJson().nextString());
+ assertEquals("b", reader.nextString());
+ reader.endObject();
+ }
+
+ /** Peek a value, then read it, recursively. */
+ private void readValue(JsonReader reader, boolean peekJsonFirst) throws IOException {
+ JsonReader.Token token = reader.peek();
+ if (peekJsonFirst) {
+ readValue(reader.peekJson(), false);
+ }
+
+ switch (token) {
+ case BEGIN_ARRAY:
+ reader.beginArray();
+ while (reader.hasNext()) {
+ readValue(reader, peekJsonFirst);
+ }
+ reader.peekJson().endArray();
+ reader.endArray();
+ break;
+ case BEGIN_OBJECT:
+ reader.beginObject();
+ while (reader.hasNext()) {
+ assertNotNull(reader.peekJson().nextName());
+ assertNotNull(reader.nextName());
+ readValue(reader, peekJsonFirst);
+ }
+ reader.peekJson().endObject();
+ reader.endObject();
+ break;
+ case STRING:
+ reader.nextString();
+ break;
+ case NUMBER:
+ reader.nextDouble();
+ break;
+ case BOOLEAN:
+ reader.nextBoolean();
+ break;
+ case NULL:
+ reader.nextNull();
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
}
diff --git a/pom.xml b/pom.xml
index c6d1cc1..a5814c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
3.1.0
- 1.15.0
+ 1.16.0
0.15