Merge pull request #704 from square/jwilson.1007.peekutf8

Implement peekJson() for JsonUtf8Reader
This commit is contained in:
Jesse Wilson
2018-10-08 12:27:02 -04:00
committed by GitHub
5 changed files with 90 additions and 8 deletions

View File

@@ -497,8 +497,7 @@ public abstract class JsonReader implements Closeable {
* jsonReader.nextInt() // Returns 456, reader contains 789 and ]. * jsonReader.nextInt() // Returns 456, reader contains 789 and ].
* }</pre> * }</pre>
*/ */
// TODO(jwilson): make this public once it's supported in JsonUtf8Reader. public abstract JsonReader peekJson();
abstract JsonReader peekJson();
/** /**
* Returns a <a href="http://goessner.net/articles/JsonPath/">JsonPath</a> to * Returns a <a href="http://goessner.net/articles/JsonPath/">JsonPath</a> to

View File

@@ -98,6 +98,27 @@ final class JsonUtf8Reader extends JsonReader {
pushScope(JsonScope.EMPTY_DOCUMENT); 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 { @Override public void beginArray() throws IOException {
int p = peeked; int p = peeked;
if (p == PEEKED_NONE) { if (p == PEEKED_NONE) {
@@ -1051,8 +1072,8 @@ final class JsonUtf8Reader extends JsonReader {
return found; return found;
} }
@Override JsonReader peekJson() { @Override public JsonReader peekJson() {
throw new UnsupportedOperationException("TODO"); return new JsonUtf8Reader(this);
} }
@Override public String toString() { @Override public String toString() {

View File

@@ -318,7 +318,7 @@ final class JsonValueReader extends JsonReader {
} }
} }
@Override JsonReader peekJson() { @Override public JsonReader peekJson() {
return new JsonValueReader(this); return new JsonValueReader(this);
} }

View File

@@ -33,6 +33,7 @@ import static com.squareup.moshi.JsonReader.Token.STRING;
import static com.squareup.moshi.TestUtil.repeat; import static com.squareup.moshi.TestUtil.repeat;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue; import static org.junit.Assume.assumeTrue;
@@ -988,7 +989,6 @@ public final class JsonReaderTest {
@Test public void basicPeekJson() throws IOException { @Test public void basicPeekJson() throws IOException {
JsonReader reader = newReader("{\"a\":12,\"b\":[34,56],\"c\":78}"); JsonReader reader = newReader("{\"a\":12,\"b\":[34,56],\"c\":78}");
assumeTrue(reader instanceof JsonValueReader); // Not implemented for JsonUtf8Reader yet!
reader.beginObject(); reader.beginObject();
assertThat(reader.nextName()).isEqualTo("a"); assertThat(reader.nextName()).isEqualTo("a");
assertThat(reader.nextInt()).isEqualTo(12); assertThat(reader.nextInt()).isEqualTo(12);
@@ -1021,7 +1021,6 @@ public final class JsonReaderTest {
*/ */
@Test public void peekJsonReader() throws IOException { @Test public void peekJsonReader() throws IOException {
JsonReader reader = newReader("[12,34,{\"a\":56,\"b\":78},90]"); 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++) { for (int i = 0; i < 12; i++) {
readPeek12Steps(reader.peekJson(), i, 12); readPeek12Steps(reader.peekJson(), i, 12);
readPeek12Steps(reader, i, i + 1); readPeek12Steps(reader, i, i + 1);
@@ -1084,4 +1083,67 @@ public final class JsonReaderTest {
assertThat(reader.getPath()).isEqualTo("$"); 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();
}
}
} }

View File

@@ -35,7 +35,7 @@
<maven-assembly.version>3.1.0</maven-assembly.version> <maven-assembly.version>3.1.0</maven-assembly.version>
<!-- Dependencies --> <!-- Dependencies -->
<okio.version>1.15.0</okio.version> <okio.version>1.16.0</okio.version>
<!-- Test Dependencies --> <!-- Test Dependencies -->
<compile-testing.version>0.15</compile-testing.version> <compile-testing.version>0.15</compile-testing.version>