diff --git a/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java b/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java index 691fade..7d4b5bc 100644 --- a/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java +++ b/moshi/src/main/java/com/squareup/moshi/ClassJsonAdapter.java @@ -21,6 +21,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; import java.util.Set; @@ -46,8 +47,10 @@ final class ClassJsonAdapter extends JsonAdapter { public static final JsonAdapter.Factory FACTORY = new JsonAdapter.Factory() { @Override public @Nullable JsonAdapter create( Type type, Set annotations, Moshi moshi) { - if (!(type instanceof Class)) return null; - Class rawType = (Class) type; + if (!(type instanceof Class || type instanceof ParameterizedType)) { + return null; + } + Class rawType = Types.getRawType(type); if (rawType.isInterface() || rawType.isEnum()) return null; if (Util.isPlatformType(rawType) && !Types.isAllowedPlatformType(rawType)) { throw new IllegalArgumentException("Platform " @@ -74,7 +77,7 @@ final class ClassJsonAdapter extends JsonAdapter { ClassFactory classFactory = ClassFactory.get(rawType); Map> fields = new TreeMap<>(); - for (Type t = rawType; t != Object.class; t = Types.getGenericSuperclass(t)) { + for (Type t = type; t != Object.class; t = Types.getGenericSuperclass(t)) { createFieldBindings(moshi, t, fields); } return new ClassJsonAdapter<>(classFactory, fields).nullSafe(); diff --git a/moshi/src/test/java/com/squareup/moshi/ClassJsonAdapterTest.java b/moshi/src/test/java/com/squareup/moshi/ClassJsonAdapterTest.java index 5a6fa24..b6f5d7e 100644 --- a/moshi/src/test/java/com/squareup/moshi/ClassJsonAdapterTest.java +++ b/moshi/src/test/java/com/squareup/moshi/ClassJsonAdapterTest.java @@ -444,6 +444,23 @@ public final class ClassJsonAdapterTest { assertThat(fromJson.zipCode).isEqualTo("94043"); } + static final class Box { + final T data; + + Box(T data) { + this.data = data; + } + } + + @Test public void parameterizedType() throws Exception { + @SuppressWarnings("unchecked") + JsonAdapter> adapter = (JsonAdapter>) ClassJsonAdapter.FACTORY.create( + Types.newParameterizedTypeWithOwner(ClassJsonAdapterTest.class, Box.class, Integer.class), + NO_ANNOTATIONS, moshi); + assertThat(adapter.fromJson("{\"data\":5}").data).isEqualTo(5); + assertThat(adapter.toJson(new Box<>(5))).isEqualTo("{\"data\":5}"); + } + private String toJson(Class type, T value) throws IOException { @SuppressWarnings("unchecked") // Factory.create returns an adapter that matches its argument. JsonAdapter jsonAdapter = (JsonAdapter) ClassJsonAdapter.FACTORY.create(