Merge pull request #712 from square/jwilson.1019.use_flatten

Don't decode into memory in RuntimeJsonAdapterFactory
This commit is contained in:
Jesse Wilson
2018-10-19 12:18:20 -04:00
committed by GitHub
2 changed files with 32 additions and 8 deletions

View File

@@ -26,9 +26,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.CheckReturnValue;
@@ -182,12 +180,12 @@ final class RuntimeJsonAdapterFactory<T> implements JsonAdapter.Factory {
+ ". Register this subtype.");
}
JsonAdapter<Object> adapter = jsonAdapters.get(labelIndex);
Map<String, Object> jsonValue = (Map<String, Object>) adapter.toJsonValue(value);
Map<String, Object> valueWithLabel = new LinkedHashMap<>(1 + jsonValue.size());
valueWithLabel.put(labelKey, labels.get(labelIndex));
valueWithLabel.putAll(jsonValue);
objectJsonAdapter.toJson(writer, valueWithLabel);
writer.beginObject();
writer.name(labelKey).value(labels.get(labelIndex));
int flattenToken = writer.beginFlatten();
adapter.toJson(writer, value);
writer.endFlatten(flattenToken);
writer.endObject();
}
@Override public String toString() {

View File

@@ -180,6 +180,24 @@ public final class RuntimeJsonAdapterFactoryTest {
}
}
/**
* Longs that do not have an exact double representation are problematic for JSON. It is a bad
* idea to use JSON for these values! But Moshi tries to retain long precision where possible.
*/
@Test public void unportableTypes() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(RuntimeJsonAdapterFactory.of(Message.class, "type")
.withSubtype(MessageWithUnportableTypes.class, "unportable"))
.build();
JsonAdapter<Message> adapter = moshi.adapter(Message.class);
assertThat(adapter.toJson(new MessageWithUnportableTypes(9007199254740993L)))
.isEqualTo("{\"type\":\"unportable\",\"long_value\":9007199254740993}");
MessageWithUnportableTypes decoded = (MessageWithUnportableTypes) adapter.fromJson(
"{\"type\":\"unportable\",\"long_value\":9007199254740993}");
assertThat(decoded.long_value).isEqualTo(9007199254740993L);
}
interface Message {
}
@@ -226,4 +244,12 @@ public final class RuntimeJsonAdapterFactoryTest {
return "EmptyMessage";
}
}
static final class MessageWithUnportableTypes implements Message {
final long long_value;
MessageWithUnportableTypes(long long_value) {
this.long_value = long_value;
}
}
}