From 6125d8c7b1275f4f03e75b6a2928b8958b00fa9b Mon Sep 17 00:00:00 2001 From: Jesse Wilson Date: Fri, 19 Oct 2018 12:03:44 -0400 Subject: [PATCH] Don't decode into memory in RuntimeJsonAdapterFactory Instead use our new flatten API to decode directly to the stream. --- .../adapters/RuntimeJsonAdapterFactory.java | 14 +++++----- .../RuntimeJsonAdapterFactoryTest.java | 26 +++++++++++++++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/adapters/src/main/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactory.java b/adapters/src/main/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactory.java index 0cb5f69..971a4ac 100644 --- a/adapters/src/main/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactory.java +++ b/adapters/src/main/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactory.java @@ -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 implements JsonAdapter.Factory { + ". Register this subtype."); } JsonAdapter adapter = jsonAdapters.get(labelIndex); - Map jsonValue = (Map) adapter.toJsonValue(value); - - Map 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() { diff --git a/adapters/src/test/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactoryTest.java b/adapters/src/test/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactoryTest.java index 7491db9..31b59a2 100644 --- a/adapters/src/test/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactoryTest.java +++ b/adapters/src/test/java/com/squareup/moshi/adapters/RuntimeJsonAdapterFactoryTest.java @@ -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 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; + } + } }