mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Introduced tags to reader/writers (#1227)
* Introduced tags to reader/writers * Removed getTags method * Added type safety to tag methods * Changed to explicit class comparison * Removed ? extends for tags * Switched to LinkedHashMap * Allowed polymorphism for tag values * Simplified tags tests
This commit is contained in:
@@ -21,6 +21,7 @@ import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
@@ -197,6 +198,8 @@ public abstract class JsonReader implements Closeable {
|
||||
/** True to throw a {@link JsonDataException} on any attempt to call {@link #skipValue()}. */
|
||||
boolean failOnUnknown;
|
||||
|
||||
private Map<Class<?>, Object> tags;
|
||||
|
||||
/** Returns a new instance that reads UTF-8 encoded JSON from {@code source}. */
|
||||
@CheckReturnValue
|
||||
public static JsonReader of(BufferedSource source) {
|
||||
@@ -569,6 +572,27 @@ public abstract class JsonReader implements Closeable {
|
||||
return JsonScope.getPath(stackSize, scopes, pathNames, pathIndices);
|
||||
}
|
||||
|
||||
/** Returns the tag value for the given class key. */
|
||||
@SuppressWarnings("unchecked")
|
||||
@CheckReturnValue
|
||||
public final @Nullable <T> T tag(Class<T> clazz) {
|
||||
if (tags == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) tags.get(clazz);
|
||||
}
|
||||
|
||||
/** Assigns the tag value using the given class key and value. */
|
||||
public final <T> void setTag(Class<T> clazz, T value) {
|
||||
if (!clazz.isAssignableFrom(value.getClass())) {
|
||||
throw new IllegalArgumentException("Tag value must be of type " + clazz.getName());
|
||||
}
|
||||
if (tags == null) {
|
||||
tags = new LinkedHashMap<>();
|
||||
}
|
||||
tags.put(clazz, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@@ -24,6 +24,7 @@ import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.CheckReturnValue;
|
||||
@@ -171,6 +172,8 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
||||
*/
|
||||
int flattenStackSize = -1;
|
||||
|
||||
private Map<Class<?>, Object> tags;
|
||||
|
||||
/** Returns a new instance that writes UTF-8 encoded JSON to {@code sink}. */
|
||||
@CheckReturnValue
|
||||
public static JsonWriter of(BufferedSink sink) {
|
||||
@@ -561,4 +564,25 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
||||
public final String getPath() {
|
||||
return JsonScope.getPath(stackSize, scopes, pathNames, pathIndices);
|
||||
}
|
||||
|
||||
/** Returns the tag value for the given class key. */
|
||||
@SuppressWarnings("unchecked")
|
||||
@CheckReturnValue
|
||||
public final @Nullable <T> T tag(Class<T> clazz) {
|
||||
if (tags == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) tags.get(clazz);
|
||||
}
|
||||
|
||||
/** Assigns the tag value using the given class key and value. */
|
||||
public final <T> void setTag(Class<T> clazz, T value) {
|
||||
if (!clazz.isAssignableFrom(value.getClass())) {
|
||||
throw new IllegalArgumentException("Tag value must be of type " + clazz.getName());
|
||||
}
|
||||
if (tags == null) {
|
||||
tags = new LinkedHashMap<>();
|
||||
}
|
||||
tags.put(clazz, value);
|
||||
}
|
||||
}
|
||||
|
@@ -1433,6 +1433,27 @@ public final class JsonReaderTest {
|
||||
assertThat(reader.nextString()).isEqualTo("d");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void tags() throws IOException {
|
||||
JsonReader reader = newReader("{}");
|
||||
assertThat(reader.tag(Integer.class)).isNull();
|
||||
assertThat(reader.tag(CharSequence.class)).isNull();
|
||||
|
||||
reader.setTag(Integer.class, 1);
|
||||
reader.setTag(CharSequence.class, "Foo");
|
||||
try {
|
||||
reader.setTag((Class) CharSequence.class, 1);
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertThat(expected).hasMessage("Tag value must be of type java.lang.CharSequence");
|
||||
}
|
||||
|
||||
assertThat(reader.tag(Integer.class)).isEqualTo(1).isInstanceOf(Integer.class);
|
||||
assertThat(reader.tag(CharSequence.class)).isEqualTo("Foo").isInstanceOf(String.class);
|
||||
assertThat(reader.tag(String.class)).isNull();
|
||||
}
|
||||
|
||||
/** Peek a value, then read it, recursively. */
|
||||
private void readValue(JsonReader reader, boolean peekJsonFirst) throws IOException {
|
||||
JsonReader.Token token = reader.peek();
|
||||
|
@@ -953,4 +953,25 @@ public final class JsonWriterTest {
|
||||
writer.endObject();
|
||||
assertThat(factory.json()).isEqualTo("{}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void tags() throws IOException {
|
||||
JsonWriter writer = factory.newWriter();
|
||||
assertThat(writer.tag(Integer.class)).isNull();
|
||||
assertThat(writer.tag(CharSequence.class)).isNull();
|
||||
|
||||
writer.setTag(Integer.class, 1);
|
||||
writer.setTag(CharSequence.class, "Foo");
|
||||
try {
|
||||
writer.setTag((Class) CharSequence.class, 1);
|
||||
fail();
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertThat(expected).hasMessage("Tag value must be of type java.lang.CharSequence");
|
||||
}
|
||||
|
||||
assertThat(writer.tag(Integer.class)).isEqualTo(1).isInstanceOf(Integer.class);
|
||||
assertThat(writer.tag(CharSequence.class)).isEqualTo("Foo").isInstanceOf(String.class);
|
||||
assertThat(writer.tag(String.class)).isNull();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user