From d27eaa161ad109f81e1e298aa26b3256c433474c Mon Sep 17 00:00:00 2001 From: Eric Cochran Date: Sat, 28 Jan 2017 20:54:42 -0800 Subject: [PATCH] Add adapter(Type, Class) --- .../main/java/com/squareup/moshi/Moshi.java | 5 +++ .../main/java/com/squareup/moshi/Types.java | 37 +++++++++++++++++++ .../java/com/squareup/moshi/TypesTest.java | 18 +++++++++ 3 files changed, 60 insertions(+) diff --git a/moshi/src/main/java/com/squareup/moshi/Moshi.java b/moshi/src/main/java/com/squareup/moshi/Moshi.java index 39e83f3..16cedad 100644 --- a/moshi/src/main/java/com/squareup/moshi/Moshi.java +++ b/moshi/src/main/java/com/squareup/moshi/Moshi.java @@ -61,6 +61,11 @@ public final class Moshi { return adapter(type, Util.NO_ANNOTATIONS); } + public JsonAdapter adapter(Type type, Class annotationType) { + return adapter(type, + Collections.singleton(Types.createJsonQualifierImplementation(annotationType))); + } + @SuppressWarnings("unchecked") // Factories are required to return only matching JsonAdapters. public JsonAdapter adapter(Type type, Set annotations) { type = Types.canonicalize(type); diff --git a/moshi/src/main/java/com/squareup/moshi/Types.java b/moshi/src/main/java/com/squareup/moshi/Types.java index 67cac08..02a841f 100644 --- a/moshi/src/main/java/com/squareup/moshi/Types.java +++ b/moshi/src/main/java/com/squareup/moshi/Types.java @@ -15,10 +15,14 @@ */ package com.squareup.moshi; +import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; @@ -137,6 +141,39 @@ public final class Types { } } + @SuppressWarnings("unchecked") + static T createJsonQualifierImplementation(final Class annotationType) { + if (!annotationType.isAnnotation()) { + throw new IllegalArgumentException(annotationType + " must be an annotation."); + } + if (!annotationType.isAnnotationPresent(JsonQualifier.class)) { + throw new IllegalArgumentException(annotationType + " must have @JsonQualifier."); + } + if (annotationType.getDeclaredMethods().length != 0) { + throw new IllegalArgumentException(annotationType + " must not declare methods."); + } + return (T) Proxy.newProxyInstance(annotationType.getClassLoader(), + new Class[] { annotationType }, new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + String methodName = method.getName(); + switch (methodName) { + case "annotationType": + return annotationType; + case "equals": + Object o = args[0]; + return annotationType.isInstance(o); + case "hashCode": + return 0; + case "toString": + return "@" + annotationType.getName() + "()"; + default: + return method.invoke(proxy, args); + } + } + }); + } + static boolean equal(Object a, Object b) { return a == b || (a != null && a.equals(b)); } diff --git a/moshi/src/test/java/com/squareup/moshi/TypesTest.java b/moshi/src/test/java/com/squareup/moshi/TypesTest.java index a41070e..5b91809 100644 --- a/moshi/src/test/java/com/squareup/moshi/TypesTest.java +++ b/moshi/src/test/java/com/squareup/moshi/TypesTest.java @@ -15,6 +15,7 @@ */ package com.squareup.moshi; +import java.lang.annotation.Retention; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; @@ -23,6 +24,7 @@ import java.util.Map; import java.util.Properties; import org.junit.Test; +import static java.lang.annotation.RetentionPolicy.RUNTIME; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -143,4 +145,20 @@ public final class TypesTest { assertThat(Types.mapKeyAndValueTypes(StringIntegerMap.class, StringIntegerMap.class)) .containsExactly(String.class, Integer.class); } + + @Test public void createJsonQualifierImplementation() throws Exception { + TestQualifier actual = Types.createJsonQualifierImplementation(TestQualifier.class); + TestQualifier expected = + (TestQualifier) TypesTest.class.getDeclaredField("unused").getAnnotations()[0]; + assertThat(actual.annotationType()).isEqualTo(TestQualifier.class); + assertThat(actual).isEqualTo(expected); + assertThat(actual).isNotEqualTo(null); + assertThat(actual.hashCode()).isEqualTo(expected.hashCode()); + assertThat(actual.getClass()).isNotEqualTo(TestQualifier.class); + } + + @TestQualifier private static Object unused; + + @Retention(RUNTIME) @JsonQualifier @interface TestQualifier { + } }