mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Merge pull request #1185 from square/jwilson.0801.public_promoteNameToValue
Make JsonReader.promoteNameToValue() a public API
This commit is contained in:
@@ -514,8 +514,19 @@ public abstract class JsonReader implements Closeable {
|
||||
/**
|
||||
* Changes the reader to treat the next name as a string value. This is useful for map adapters so
|
||||
* that arbitrary type adapters can use {@link #nextString} to read a name value.
|
||||
*
|
||||
* <p>In this example, calling this method allows two sequential calls to {@link #nextString()}:
|
||||
* <pre> {@code
|
||||
*
|
||||
* JsonReader reader = JsonReader.of(new Buffer().writeUtf8("{\"a\":\"b\"}"));
|
||||
* reader.beginObject();
|
||||
* reader.promoteNameToValue();
|
||||
* assertEquals("a", reader.nextString());
|
||||
* assertEquals("b", reader.nextString());
|
||||
* reader.endObject();
|
||||
* }</pre>
|
||||
*/
|
||||
abstract void promoteNameToValue() throws IOException;
|
||||
public abstract void promoteNameToValue() throws IOException;
|
||||
|
||||
/**
|
||||
* A set of strings to be chosen with {@link #selectName} or {@link #selectString}. This prepares
|
||||
|
@@ -1158,7 +1158,7 @@ final class JsonUtf8Reader extends JsonReader {
|
||||
}
|
||||
}
|
||||
|
||||
@Override void promoteNameToValue() throws IOException {
|
||||
@Override public void promoteNameToValue() throws IOException {
|
||||
if (hasNext()) {
|
||||
peekedString = nextName();
|
||||
peeked = PEEKED_BUFFERED;
|
||||
|
@@ -162,12 +162,13 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
throw new IllegalStateException("JsonWriter is closed.");
|
||||
}
|
||||
int context = peekScope();
|
||||
if ((context != EMPTY_OBJECT && context != NONEMPTY_OBJECT) || deferredName != null) {
|
||||
if ((context != EMPTY_OBJECT && context != NONEMPTY_OBJECT)
|
||||
|| deferredName != null
|
||||
|| promoteValueToName) {
|
||||
throw new IllegalStateException("Nesting problem.");
|
||||
}
|
||||
deferredName = name;
|
||||
pathNames[stackSize - 1] = name;
|
||||
promoteValueToName = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -184,6 +185,7 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
return nullValue();
|
||||
}
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(value);
|
||||
}
|
||||
writeDeferredName();
|
||||
@@ -236,6 +238,7 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||
}
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(Double.toString(value));
|
||||
}
|
||||
writeDeferredName();
|
||||
@@ -247,6 +250,7 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
|
||||
@Override public JsonWriter value(long value) throws IOException {
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(Long.toString(value));
|
||||
}
|
||||
writeDeferredName();
|
||||
@@ -267,6 +271,7 @@ final class JsonUtf8Writer extends JsonWriter {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||
}
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(string);
|
||||
}
|
||||
writeDeferredName();
|
||||
|
@@ -330,7 +330,7 @@ final class JsonValueReader extends JsonReader {
|
||||
return new JsonValueReader(this);
|
||||
}
|
||||
|
||||
@Override void promoteNameToValue() throws IOException {
|
||||
@Override public void promoteNameToValue() throws IOException {
|
||||
if (hasNext()) {
|
||||
String name = nextName();
|
||||
push(name);
|
||||
|
@@ -130,17 +130,17 @@ final class JsonValueWriter extends JsonWriter {
|
||||
if (stackSize == 0) {
|
||||
throw new IllegalStateException("JsonWriter is closed.");
|
||||
}
|
||||
if (peekScope() != EMPTY_OBJECT || deferredName != null) {
|
||||
if (peekScope() != EMPTY_OBJECT || deferredName != null || promoteValueToName) {
|
||||
throw new IllegalStateException("Nesting problem.");
|
||||
}
|
||||
deferredName = name;
|
||||
pathNames[stackSize - 1] = name;
|
||||
promoteValueToName = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public JsonWriter value(@Nullable String value) throws IOException {
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(value);
|
||||
}
|
||||
add(value);
|
||||
@@ -184,6 +184,7 @@ final class JsonValueWriter extends JsonWriter {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||
}
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(Double.toString(value));
|
||||
}
|
||||
add(value);
|
||||
@@ -193,6 +194,7 @@ final class JsonValueWriter extends JsonWriter {
|
||||
|
||||
@Override public JsonWriter value(long value) throws IOException {
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(Long.toString(value));
|
||||
}
|
||||
add(value);
|
||||
@@ -223,6 +225,7 @@ final class JsonValueWriter extends JsonWriter {
|
||||
? ((BigDecimal) value)
|
||||
: new BigDecimal(value.toString());
|
||||
if (promoteValueToName) {
|
||||
promoteValueToName = false;
|
||||
return name(bigDecimalValue.toString());
|
||||
}
|
||||
add(bigDecimalValue);
|
||||
|
@@ -443,8 +443,20 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
||||
/**
|
||||
* Changes the writer to treat the next value as a string name. This is useful for map adapters so
|
||||
* that arbitrary type adapters can use {@link #value} to write a name value.
|
||||
*
|
||||
* <p>In this example, calling this method allows two sequential calls to {@link #value(String)}
|
||||
* to produce the object, {@code {"a": "b"}}.
|
||||
* <pre> {@code
|
||||
*
|
||||
* JsonWriter writer = JsonWriter.of(...);
|
||||
* writer.beginObject();
|
||||
* writer.promoteValueToName();
|
||||
* writer.value("a");
|
||||
* writer.value("b");
|
||||
* writer.endObject();
|
||||
* }</pre>
|
||||
*/
|
||||
final void promoteValueToName() throws IOException {
|
||||
public final void promoteValueToName() throws IOException {
|
||||
int context = peekScope();
|
||||
if (context != NONEMPTY_OBJECT && context != EMPTY_OBJECT) {
|
||||
throw new IllegalStateException("Nesting problem.");
|
||||
|
@@ -20,7 +20,6 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
@@ -1158,6 +1157,85 @@ public final class JsonReaderTest {
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
@Test public void promoteStringNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"a\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
assertEquals("a", reader.nextString());
|
||||
assertEquals("b", reader.nextString());
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
@Test public void promoteDoubleNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"5\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
assertEquals(5.0, reader.nextDouble(), 0.0);
|
||||
assertEquals("b", reader.nextString());
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
@Test public void promoteLongNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"5\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
assertEquals(5L, reader.nextLong());
|
||||
assertEquals("b", reader.nextString());
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
@Test public void promoteNullNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"null\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (JsonDataException expected) {
|
||||
}
|
||||
assertEquals("null", reader.nextString());
|
||||
}
|
||||
|
||||
@Test public void promoteBooleanNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"true\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
try {
|
||||
reader.nextBoolean();
|
||||
fail();
|
||||
} catch (JsonDataException expected) {
|
||||
}
|
||||
assertEquals("true", reader.nextString());
|
||||
}
|
||||
|
||||
@Test public void promoteBooleanNameToValueCannotBeReadAsName() throws IOException {
|
||||
JsonReader reader = newReader("{\"true\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
try {
|
||||
reader.nextName();
|
||||
fail();
|
||||
} catch (JsonDataException expected) {
|
||||
}
|
||||
assertEquals("true", reader.nextString());
|
||||
}
|
||||
|
||||
@Test public void promoteSkippedNameToValue() throws IOException {
|
||||
JsonReader reader = newReader("{\"true\":\"b\"}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
reader.skipValue();
|
||||
assertEquals("b", reader.nextString());
|
||||
}
|
||||
|
||||
@Test public void promoteNameToValueAtEndOfObject() throws IOException {
|
||||
JsonReader reader = newReader("{}");
|
||||
reader.beginObject();
|
||||
reader.promoteNameToValue();
|
||||
assertThat(reader.hasNext()).isFalse();
|
||||
reader.endObject();
|
||||
}
|
||||
|
||||
@Test public void optionsStrings() {
|
||||
String[] options = new String[] { "a", "b", "c" };
|
||||
JsonReader.Options abc = JsonReader.Options.of("a", "b", "c");
|
||||
|
@@ -609,7 +609,7 @@ public final class JsonWriterTest {
|
||||
assertThat(expected).hasMessage("Nesting problem.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test public void danglingNameFails() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
@@ -814,4 +814,88 @@ public final class JsonWriterTest {
|
||||
assertThat(e).hasMessage("Map keys must be non-null");
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void promoteStringNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
writer.value("a");
|
||||
writer.value("b");
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{\"a\":\"b\"}");
|
||||
}
|
||||
|
||||
@Test public void promoteDoubleNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
writer.value(5.0);
|
||||
writer.value("b");
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{\"5.0\":\"b\"}");
|
||||
}
|
||||
|
||||
@Test public void promoteLongNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
writer.value(5L);
|
||||
writer.value("b");
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{\"5\":\"b\"}");
|
||||
}
|
||||
|
||||
@Test public void promoteNumberNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
writer.value(BigInteger.ONE);
|
||||
writer.value("b");
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{\"1\":\"b\"}");
|
||||
}
|
||||
|
||||
@Test public void promoteNullNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
try {
|
||||
writer.nullValue();
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
assertThat(expected).hasMessage("null cannot be used as a map key in JSON at path $.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void promoteBooleanNameToValue() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
try {
|
||||
writer.value(true);
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
assertThat(expected).hasMessage("Boolean cannot be used as a map key in JSON at path $.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void promoteNameToValueCannotBeWrittenAsName() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
try {
|
||||
writer.name("a");
|
||||
fail();
|
||||
} catch (IllegalStateException expected) {
|
||||
assertThat(expected).hasMessage("Nesting problem.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test public void promoteNameToValueAtEndOfObject() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
writer.beginObject();
|
||||
writer.promoteValueToName();
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{}");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user