Updated JSONObjectOutputStream to support extended generics

This commit is contained in:
Ziver Koc 2015-11-05 02:07:08 +01:00
parent 2dae3a6f01
commit 8ca2f21c7c
3 changed files with 54 additions and 13 deletions

10
Zutil.iml Normal file → Executable file
View file

@ -32,5 +32,15 @@
<jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" type="SOURCES" /> <jarDirectory url="file://$MODULE_DIR$/libs" recursive="false" type="SOURCES" />
</library> </library>
</orderEntry> </orderEntry>
<orderEntry type="module-library" scope="TEST">
<library name="JUnit4">
<CLASSES>
<root url="jar://$APPLICATION_HOME_DIR$/lib/junit-4.12.jar!/" />
<root url="jar://$APPLICATION_HOME_DIR$/lib/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component> </component>
</module> </module>

44
src/zutil/ClassUtil.java Normal file → Executable file
View file

@ -27,8 +27,11 @@ package zutil;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
/** /**
* This class include some utility functions for classes * This class include some utility functions for classes
@ -83,15 +86,42 @@ public class ClassUtil {
} }
/**
* @param field is the field to return the generics from
* @return the generics assigned to a specific field or a empty list
*/
public static Class<?>[] getGenericClasses(Field field){ public static Class<?>[] getGenericClasses(Field field){
Class[] classArray = new Class[0]; return getGenericClasses(field.getGenericType());
Type genericFieldType = field.getGenericType(); }
/**
* Traverses the class hierarchy and searches for the given super class or interface
* and returns the assigned generic types.
*
* @param c the source class
* @param superClass is the super class to search for
* @return the generics for a specific super class or a empty list if
* there is no generics or the super class is not found
*/
public static Class<?>[] getGenericClasses(Class<?> c, Class<?> superClass){
// Search for the super class
while (c.getSuperclass() != Object.class && !superClass.isAssignableFrom(c.getSuperclass()))
c = c.getSuperclass();
// Did we find the super class?
if (superClass.isAssignableFrom(c.getSuperclass()))
return getGenericClasses(c.getGenericSuperclass());
if(genericFieldType instanceof ParameterizedType){ return new Class[0];
ParameterizedType aType = (ParameterizedType) genericFieldType; }
Type[] fieldArgTypes = aType.getActualTypeArguments(); private static Class<?>[] getGenericClasses(Type genericType){
classArray = Arrays.copyOf(fieldArgTypes, fieldArgTypes.length, Class[].class); if(genericType instanceof ParameterizedType){
ParameterizedType aType = (ParameterizedType) genericType;
Type[] argTypes = aType.getActualTypeArguments();
Class<?>[] classArray = new Class<?>[argTypes.length];
for(int i=0; i<classArray.length; ++i) {
classArray[i] = (Class<?>) argTypes[i];
}
return classArray;
} }
return classArray; return new Class[0];
} }
} }

View file

@ -129,8 +129,8 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
protected Object readType(Class<?> type, Class<?>[] genType, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException, NoSuchFieldException { protected Object readType(Class<?> type, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException, NoSuchFieldException {
if(json == null) if(json == null || type == null)
return null; return null;
// Field type is a primitive? // Field type is a primitive?
if(type.isPrimitive() || String.class.isAssignableFrom(type)){ if(type.isPrimitive() || String.class.isAssignableFrom(type)){
@ -142,25 +142,27 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
else{ else{
Object array = Array.newInstance(type.getComponentType(), json.size()); Object array = Array.newInstance(type.getComponentType(), json.size());
for(int i=0; i<json.size(); i++){ for(int i=0; i<json.size(); i++){
Array.set(array, i, readType(type.getComponentType(), null, key, json.get(i))); Array.set(array, i, readType(type.getComponentType(), key, json.get(i)));
} }
return array; return array;
} }
} }
else if(List.class.isAssignableFrom(type)){ else if(List.class.isAssignableFrom(type)){
Class<?>[] genType = ClassUtil.getGenericClasses(type, List.class);
List list = (List)type.newInstance(); List list = (List)type.newInstance();
for(int i=0; i<json.size(); i++){ for(int i=0; i<json.size(); i++){
list.add(readType(genType[0], null, key, json.get(i))); list.add(readType((genType.length>=1? genType[0] : null), key, json.get(i)));
} }
return list; return list;
} }
else if(Map.class.isAssignableFrom(type)){ else if(Map.class.isAssignableFrom(type)){
Class<?>[] genType = ClassUtil.getGenericClasses(type, Map.class);
Map map = (Map)type.newInstance(); Map map = (Map)type.newInstance();
for(Iterator<String> it=json.keyIterator(); it.hasNext();){ for(Iterator<String> it=json.keyIterator(); it.hasNext();){
String subKey = it.next(); String subKey = it.next();
map.put( map.put(
subKey, subKey,
readType(genType[1], null, subKey, json.get(subKey))); readType((genType.length>=2? genType[1] : null), subKey, json.get(subKey)));
} }
return map; return map;
} }
@ -210,7 +212,6 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
field.setAccessible(true); field.setAccessible(true);
field.set(obj, readType( field.set(obj, readType(
field.getType(), field.getType(),
ClassUtil.getGenericClasses(field),
field.getName(), field.getName(),
json.get(field.getName()))); json.get(field.getName())));
} }