mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 07:59: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.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.CheckReturnValue;
|
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()}. */
|
/** True to throw a {@link JsonDataException} on any attempt to call {@link #skipValue()}. */
|
||||||
boolean failOnUnknown;
|
boolean failOnUnknown;
|
||||||
|
|
||||||
|
private Map<Class<?>, Object> tags;
|
||||||
|
|
||||||
/** Returns a new instance that reads UTF-8 encoded JSON from {@code source}. */
|
/** Returns a new instance that reads UTF-8 encoded JSON from {@code source}. */
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
public static JsonReader of(BufferedSource source) {
|
public static JsonReader of(BufferedSource source) {
|
||||||
@@ -569,6 +572,27 @@ public abstract class JsonReader implements Closeable {
|
|||||||
return JsonScope.getPath(stackSize, scopes, pathNames, pathIndices);
|
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
|
* 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.
|
* 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.Flushable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.CheckReturnValue;
|
import javax.annotation.CheckReturnValue;
|
||||||
@@ -171,6 +172,8 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
|||||||
*/
|
*/
|
||||||
int flattenStackSize = -1;
|
int flattenStackSize = -1;
|
||||||
|
|
||||||
|
private Map<Class<?>, Object> tags;
|
||||||
|
|
||||||
/** Returns a new instance that writes UTF-8 encoded JSON to {@code sink}. */
|
/** Returns a new instance that writes UTF-8 encoded JSON to {@code sink}. */
|
||||||
@CheckReturnValue
|
@CheckReturnValue
|
||||||
public static JsonWriter of(BufferedSink sink) {
|
public static JsonWriter of(BufferedSink sink) {
|
||||||
@@ -561,4 +564,25 @@ public abstract class JsonWriter implements Closeable, Flushable {
|
|||||||
public final String getPath() {
|
public final String getPath() {
|
||||||
return JsonScope.getPath(stackSize, scopes, pathNames, pathIndices);
|
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");
|
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. */
|
/** Peek a value, then read it, recursively. */
|
||||||
private void readValue(JsonReader reader, boolean peekJsonFirst) throws IOException {
|
private void readValue(JsonReader reader, boolean peekJsonFirst) throws IOException {
|
||||||
JsonReader.Token token = reader.peek();
|
JsonReader.Token token = reader.peek();
|
||||||
|
@@ -953,4 +953,25 @@ public final class JsonWriterTest {
|
|||||||
writer.endObject();
|
writer.endObject();
|
||||||
assertThat(factory.json()).isEqualTo("{}");
|
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