Special handling for map and list types during reflection

This commit is contained in:
Aria 2023-06-16 02:45:57 -07:00
parent 665c7e920f
commit 76f9d93a8b
2 changed files with 109 additions and 17 deletions

View file

@ -1,9 +1,10 @@
package dev.zontreck.ariaslib.json; package dev.zontreck.ariaslib.json;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.lang.reflect.Field; import java.lang.reflect.*;
import java.lang.reflect.InvocationTargetException; import java.util.ArrayList;
import java.lang.reflect.Method; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -27,18 +28,49 @@ public class DynamicDeserializer {
T object = clazz.getDeclaredConstructor ( ).newInstance ( ); T object = clazz.getDeclaredConstructor ( ).newInstance ( );
Field[] fields = clazz.getDeclaredFields ( ); Field[] fields = clazz.getDeclaredFields ( );
for ( for ( Field field : fields ) {
Field field :
fields
) {
field.setAccessible ( true ); field.setAccessible ( true );
if ( field.isAnnotationPresent ( IgnoreSerialization.class ) ) if ( field.isAnnotationPresent ( IgnoreSerialization.class ) )
continue; continue;
try { try {
if ( List.class.isAssignableFrom ( field.getType ( ) ) ) {
if ( ! ( field.getType ( ).isAnnotationPresent ( DynSerial.class ) ) ) { Class<?> listType = getListType ( field );
List<Object> list = new ArrayList<> ( );
List<?> serializedList = ( List<?> ) map.get ( field.getName ( ) );
if ( serializedList != null ) {
for ( Object listItem : serializedList ) {
if ( listType.isAnnotationPresent ( DynSerial.class ) ) {
Object deserializedItem = deserialize ( ( Map<String, Object> ) listItem , listType );
list.add ( deserializedItem );
}
else {
list.add ( listItem );
}
}
}
field.set ( object , list );
}
else if ( Map.class.isAssignableFrom ( field.getType ( ) ) ) {
Class<?> valueType = getMapValueType ( field );
Map<String, Object> serializedMap = ( Map<String, Object> ) map.get ( field.getName ( ) );
if ( serializedMap != null ) {
Map<String, Object> mapValue = new HashMap<> ( );
for ( Map.Entry<String, Object> entry : serializedMap.entrySet ( ) ) {
Object deserializedValue;
if ( valueType.isAnnotationPresent ( DynSerial.class ) ) {
deserializedValue = deserialize ( ( Map<String, Object> ) entry.getValue ( ) , valueType );
}
else {
deserializedValue = entry.getValue ( );
}
mapValue.put ( entry.getKey ( ) , deserializedValue );
}
field.set ( object , mapValue );
}
}
else if ( ! field.getType ( ).isAnnotationPresent ( DynSerial.class ) ) {
field.set ( object , map.get ( field.getName ( ) ) ); field.set ( object , map.get ( field.getName ( ) ) );
} }
else { else {
@ -46,21 +78,42 @@ public class DynamicDeserializer {
field.set ( object , tmp ); field.set ( object , tmp );
} }
} catch ( Exception e ) { } catch ( Exception e ) {
// Handle any exceptions during deserialization
} }
} }
Method[] mth = clazz.getDeclaredMethods ( ); Method[] methods = clazz.getDeclaredMethods ( );
for ( for ( Method method : methods ) {
Method mt : if ( method.isAnnotationPresent ( Completed.class ) ) {
mth method.invoke ( object , true );
) {
if ( mt.isAnnotationPresent ( Completed.class ) ) {
mt.invoke ( object , true );
} }
} }
return object; return object;
}
private static Class<?> getListType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 0 ) {
return ( Class<?> ) actualTypeArgs[ 0 ];
}
}
return Object.class;
}
private static Class<?> getMapValueType ( Field field ) {
Type genericType = field.getGenericType ( );
if ( genericType instanceof ParameterizedType ) {
ParameterizedType paramType = ( ParameterizedType ) genericType;
Type[] actualTypeArgs = paramType.getActualTypeArguments ( );
if ( actualTypeArgs.length > 1 ) {
return ( Class<?> ) actualTypeArgs[ 1 ];
}
}
return Object.class;
} }
} }

View file

@ -3,7 +3,9 @@ package dev.zontreck.ariaslib.json;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class DynamicSerializer { public class DynamicSerializer {
@ -55,6 +57,11 @@ public class DynamicSerializer {
String fieldName = field.getName ( ); String fieldName = field.getName ( );
if ( ! ( fieldVal.getClass ( ).isAnnotationPresent ( DynSerial.class ) ) ) { if ( ! ( fieldVal.getClass ( ).isAnnotationPresent ( DynSerial.class ) ) ) {
// Special handler for List and Map is needed right here.
if (fieldVal instanceof List || fieldVal instanceof Map) {
// Special handling for List and Map types
fieldVal = serializeCollectionOrMap(fieldVal);
}
ret.put ( fieldName , fieldVal ); ret.put ( fieldName , fieldVal );
} }
else { else {
@ -72,4 +79,36 @@ public class DynamicSerializer {
} }
@SuppressWarnings ("unchecked")
private static Object serializeCollectionOrMap ( Object collectionOrMap ) throws InvocationTargetException, IllegalAccessException {
if ( collectionOrMap instanceof List ) {
List<Object> list = ( List<Object> ) collectionOrMap;
List<Object> serializedList = new ArrayList<> ( );
for ( Object item : list ) {
if ( item.getClass ( ).isAnnotationPresent ( DynSerial.class ) ) {
serializedList.add ( serialize ( item ) );
}
else {
serializedList.add ( item );
}
}
return serializedList;
}
else if ( collectionOrMap instanceof Map ) {
Map<String, Object> map = ( Map<String, Object> ) collectionOrMap;
Map<String, Object> serializedMap = new HashMap<> ( );
for ( Map.Entry<String, Object> entry : map.entrySet ( ) ) {
String key = entry.getKey ( );
Object value = entry.getValue ( );
if ( value.getClass ( ).isAnnotationPresent ( DynSerial.class ) ) {
value = serialize ( value );
}
serializedMap.put ( key , value );
}
return serializedMap;
}
return collectionOrMap;
}
} }