11package com .jsoniter .spi ;
22
3- import java . lang . reflect . Field ;
4- import java . lang . reflect . Method ;
5- import java . lang . reflect . Modifier ;
6- import java .lang .reflect .Type ;
3+ import com . jsoniter . JsonException ;
4+ import sun . net . www . content . text . Generic ;
5+
6+ import java .lang .reflect .* ;
77import java .util .*;
88
99public class ExtensionManager {
@@ -76,12 +76,14 @@ public synchronized static void addNewEncoder(String cacheKey, Encoder encoder)
7676 }
7777
7878 public static ClassDescriptor getClassDescriptor (Class clazz , boolean includingPrivate ) {
79+ Map <String , Type > lookup = collectTypeVariableLookup (clazz );
7980 ClassDescriptor desc = new ClassDescriptor ();
8081 desc .clazz = clazz ;
82+ desc .lookup = lookup ;
8183 desc .ctor = getCtor (clazz );
82- desc .fields = getFields (clazz , includingPrivate );
83- desc .setters = getSetters (clazz , includingPrivate );
84- desc .getters = getGetters (clazz , includingPrivate );
84+ desc .fields = getFields (lookup , clazz , includingPrivate );
85+ desc .setters = getSetters (lookup , clazz , includingPrivate );
86+ desc .getters = getGetters (lookup , clazz , includingPrivate );
8587 for (Extension extension : extensions ) {
8688 extension .updateClassDescriptor (desc );
8789 }
@@ -103,8 +105,6 @@ public static ClassDescriptor getClassDescriptor(Class clazz, boolean includingP
103105 if (binding .field != null && includingPrivate ) {
104106 binding .field .setAccessible (true );
105107 }
106- binding .clazz = clazz ;
107- binding .valueTypeLiteral = TypeLiteral .create (binding .valueType );
108108 }
109109 for (Binding binding : desc .allEncoderBindings ()) {
110110 if (binding .toNames == null ) {
@@ -113,8 +113,6 @@ public static ClassDescriptor getClassDescriptor(Class clazz, boolean includingP
113113 if (binding .field != null && includingPrivate ) {
114114 binding .field .setAccessible (true );
115115 }
116- binding .clazz = clazz ;
117- binding .valueTypeLiteral = TypeLiteral .create (binding .valueType );
118116 }
119117 return desc ;
120118 }
@@ -129,7 +127,7 @@ private static ConstructorDescriptor getCtor(Class clazz) {
129127 return cctor ;
130128 }
131129
132- private static List <Binding > getFields (Class clazz , boolean includingPrivate ) {
130+ private static List <Binding > getFields (Map < String , Type > lookup , Class clazz , boolean includingPrivate ) {
133131 ArrayList <Binding > bindings = new ArrayList <Binding >();
134132 for (Field field : getAllFields (clazz , includingPrivate )) {
135133 if (Modifier .isStatic (field .getModifiers ())) {
@@ -138,23 +136,16 @@ private static List<Binding> getFields(Class clazz, boolean includingPrivate) {
138136 if (includingPrivate ) {
139137 field .setAccessible (true );
140138 }
141- Binding binding = createBindingFromField (clazz , field );
139+ Binding binding = createBindingFromField (lookup , clazz , field );
142140 bindings .add (binding );
143141 }
144- Binding binding = new Binding ();
145- binding .fromNames = new String [0 ];
146- binding .name = "*" ;
147- binding .clazz = clazz ;
148142 return bindings ;
149143 }
150144
151- private static Binding createBindingFromField (Class clazz , Field field ) {
152- Binding binding = new Binding ();
145+ private static Binding createBindingFromField (Map < String , Type > lookup , Class clazz , Field field ) {
146+ Binding binding = new Binding (clazz , lookup , field . getGenericType () );
153147 binding .fromNames = new String []{field .getName ()};
154148 binding .name = field .getName ();
155- binding .valueType = field .getType ();
156- binding .valueTypeLiteral = TypeLiteral .create (binding .valueType );
157- binding .clazz = clazz ;
158149 binding .annotations = field .getAnnotations ();
159150 binding .field = field ;
160151 return binding ;
@@ -173,7 +164,7 @@ private static List<Field> getAllFields(Class clazz, boolean includingPrivate) {
173164 return allFields ;
174165 }
175166
176- private static List <SetterDescriptor > getSetters (Class clazz , boolean includingPrivate ) {
167+ private static List <SetterDescriptor > getSetters (Map < String , Type > lookup , Class clazz , boolean includingPrivate ) {
177168 ArrayList <SetterDescriptor > setters = new ArrayList <SetterDescriptor >();
178169 List <Method > allMethods = Arrays .asList (clazz .getMethods ());
179170 if (includingPrivate ) {
@@ -209,19 +200,17 @@ private static List<SetterDescriptor> getSetters(Class clazz, boolean includingP
209200 SetterDescriptor setter = new SetterDescriptor ();
210201 setter .method = method ;
211202 setter .methodName = methodName ;
212- Binding param = new Binding ();
203+ Binding param = new Binding (clazz , lookup , paramTypes [ 0 ] );
213204 param .fromNames = new String []{fromName };
214205 param .name = fromName ;
215- param .valueType = paramTypes [0 ];
216- param .valueTypeLiteral = TypeLiteral .create (param .valueType );
217206 param .clazz = clazz ;
218207 setter .parameters .add (param );
219208 setters .add (setter );
220209 }
221210 return setters ;
222211 }
223212
224- private static List <Binding > getGetters (Class clazz , boolean includingPrivate ) {
213+ private static List <Binding > getGetters (Map < String , Type > lookup , Class clazz , boolean includingPrivate ) {
225214 ArrayList <Binding > getters = new ArrayList <Binding >();
226215 for (Method method : clazz .getMethods ()) {
227216 if (Modifier .isStatic (method .getModifiers ())) {
@@ -244,11 +233,9 @@ private static List<Binding> getGetters(Class clazz, boolean includingPrivate) {
244233 char [] fromNameChars = toName .toCharArray ();
245234 fromNameChars [0 ] = Character .toLowerCase (fromNameChars [0 ]);
246235 toName = new String (fromNameChars );
247- Binding getter = new Binding ();
236+ Binding getter = new Binding (clazz , lookup , method . getGenericReturnType () );
248237 getter .toNames = new String []{toName };
249238 getter .name = methodName + "()" ;
250- getter .valueType = method .getGenericReturnType ();
251- getter .clazz = clazz ;
252239 getters .add (getter );
253240 }
254241 return getters ;
@@ -262,4 +249,28 @@ public static void dump() {
262249 System .err .println (cacheKey );
263250 }
264251 }
252+
253+ private static Map <String , Type > collectTypeVariableLookup (Type type ) {
254+ HashMap <String , Type > vars = new HashMap <String , Type >();
255+ if (null == type ) {
256+ return vars ;
257+ }
258+ if (type instanceof ParameterizedType ) {
259+ ParameterizedType pType = (ParameterizedType ) type ;
260+ Type [] actualTypeArguments = pType .getActualTypeArguments ();
261+ Class clazz = (Class ) pType .getRawType ();
262+ for (int i = 0 ; i < clazz .getTypeParameters ().length ; i ++) {
263+ TypeVariable variable = clazz .getTypeParameters ()[i ];
264+ vars .put (variable .getName () + "@" + clazz .getCanonicalName (), actualTypeArguments [i ]);
265+ }
266+ vars .putAll (collectTypeVariableLookup (clazz .getGenericSuperclass ()));
267+ return vars ;
268+ }
269+ if (type instanceof Class ) {
270+ Class clazz = (Class ) type ;
271+ vars .putAll (collectTypeVariableLookup (clazz .getGenericSuperclass ()));
272+ return vars ;
273+ }
274+ throw new JsonException ("unexpected type: " + type );
275+ }
265276}
0 commit comments