From 57ea7ff9f36409039ede0012680a8b0d3a2c02a2 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Fri, 12 Aug 2011 02:18:02 +0000 Subject: [PATCH] Restored this behavior for serialization: (as verified in CustomSerializerTest) First preference: a type adapter registered for the runtime type Second preference: a type adapter registered for the declared type Third preference: reflective type adapter for the runtime type (if it is a sub class of the declared type) Fourth preference: reflective type adapter for the declared type --- .../bind/TypeAdapterRuntimeTypeWrapper.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java index 337b737e..b005fdaa 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java @@ -42,13 +42,28 @@ final class TypeAdapterRuntimeTypeWrapper extends TypeAdapter { @SuppressWarnings("unchecked") @Override public void write(JsonWriter writer, T value) throws IOException { - TypeAdapter t = delegate; - if (delegate instanceof ReflectiveTypeAdapter) { - Type runtimeType = Reflection.getRuntimeTypeIfMoreSpecific(type, value); - if (runtimeType != type) { - t = context.getAdapter(TypeToken.get(runtimeType)); + // Order of preference for choosing type adapters + // First preference: a type adapter registered for the runtime type + // Second preference: a type adapter registered for the declared type + // Third preference: reflective type adapter for the runtime type (if it is a sub class of the declared type) + // Fourth preference: reflective type adapter for the declared type + + TypeAdapter chosen = delegate; + Type runtimeType = Reflection.getRuntimeTypeIfMoreSpecific(type, value); + if (runtimeType != type) { + TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType)); + if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapter)) { + // The user registered a type adapter for the runtime type, so we will use that + chosen = runtimeTypeAdapter; + } else if (!(delegate instanceof ReflectiveTypeAdapter)) { + // The user registered a type adapter for Base class, so we prefer it over the + // reflective type adapter for the runtime type + chosen = delegate; + } else { + // Use the type adapter for runtime type + chosen = runtimeTypeAdapter; } } - t.write(writer, value); + chosen.write(writer, value); } }