Added support for Enum and HasSets to JSON serializer
This commit is contained in:
parent
f4f52e997b
commit
67483895c3
4 changed files with 71 additions and 59 deletions
|
|
@ -149,7 +149,7 @@ public class DBBeanSQLResultHandler<T> implements SQLResultHandler<T> {
|
|||
if (obj == null) {
|
||||
// Cache miss create a new bean
|
||||
logger.fine("Creating new Bean(" + beanClass.getName() + ") with id: " + id);
|
||||
obj = beanClass.newInstance();
|
||||
obj = beanClass.getDeclaredConstructor().newInstance();
|
||||
obj.setId(id);
|
||||
updateBean(result, obj);
|
||||
} else if (DBBeanCache.isOutDated(obj)) {
|
||||
|
|
|
|||
|
|
@ -32,11 +32,9 @@ import zutil.parser.DataNode;
|
|||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
|
@ -47,20 +45,15 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
|
|||
protected static final String MD_CLASS = "@class";
|
||||
|
||||
private JSONParser parser;
|
||||
private HashMap<String, Class> registeredClasses;
|
||||
private HashMap<Integer, Object> objectCache;
|
||||
private HashMap<String, Class> registeredClasses = new HashMap<>();
|
||||
private HashMap<Integer, Object> objectCache = new HashMap<>();
|
||||
|
||||
|
||||
private JSONObjectInputStream() {
|
||||
this.registeredClasses = new HashMap<>();
|
||||
this.objectCache = new HashMap<>();
|
||||
}
|
||||
private JSONObjectInputStream() {}
|
||||
public JSONObjectInputStream(Reader in) {
|
||||
this();
|
||||
this.parser = new JSONParser(in);
|
||||
}
|
||||
public JSONObjectInputStream(InputStream in) {
|
||||
this();
|
||||
this.parser = new JSONParser(in);
|
||||
}
|
||||
|
||||
|
|
@ -122,13 +115,19 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
|
|||
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
protected Object readType(Class<?> type, Class<?>[] genType, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, NoSuchFieldException {
|
||||
protected Object readType(Class<?> type, Class<?>[] genericType, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
|
||||
// TODO: Don't replace the existing object if it exists
|
||||
|
||||
if (json == null || type == null)
|
||||
return null;
|
||||
// Field type is a primitive?
|
||||
if (type.isPrimitive() || String.class.isAssignableFrom(type)) {
|
||||
if (ClassUtil.isPrimitive(type) ||
|
||||
ClassUtil.isWrapper(type)) {
|
||||
return readPrimitive(type, json);
|
||||
}
|
||||
else if (type.isEnum()) {
|
||||
return Enum.valueOf((Class<? extends Enum>)type, (String) readPrimitive(String.class, json));
|
||||
}
|
||||
else if (type.isArray()) {
|
||||
if (type.getComponentType() == byte.class)
|
||||
return Base64Decoder.decodeToByte(json.getString());
|
||||
|
|
@ -140,25 +139,27 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
|
|||
return array;
|
||||
}
|
||||
}
|
||||
else if (List.class.isAssignableFrom(type)) {
|
||||
if (genType == null || genType.length < 1)
|
||||
genType = ClassUtil.getGenericClasses(type, List.class);
|
||||
List list = (List)type.newInstance();
|
||||
else if (Collection.class.isAssignableFrom(type)) {
|
||||
if (genericType == null || genericType.length < 1)
|
||||
genericType = ClassUtil.getGenericClasses(type, List.class);
|
||||
Collection list = (Collection) type.getDeclaredConstructor().newInstance();
|
||||
|
||||
for (int i=0; i<json.size(); i++) {
|
||||
list.add(readType((genType.length>=1? genType[0] : null), null, key, json.get(i)));
|
||||
list.add(readType((genericType.length>=1? genericType[0] : null), null, key, json.get(i)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(type)) {
|
||||
if (genType == null || genType.length < 2)
|
||||
genType = ClassUtil.getGenericClasses(type, Map.class);
|
||||
Map map = (Map)type.newInstance();
|
||||
if (genericType == null || genericType.length < 2)
|
||||
genericType = ClassUtil.getGenericClasses(type, Map.class);
|
||||
Map map = (Map) type.getDeclaredConstructor().newInstance();
|
||||
|
||||
for (Iterator<String> it=json.keyIterator(); it.hasNext();) {
|
||||
String subKey = it.next();
|
||||
if (json.get(subKey) != null) {
|
||||
map.put(
|
||||
subKey,
|
||||
readType((genType.length >= 2 ? genType[1] : null), null, subKey, json.get(subKey)));
|
||||
readType((genericType.length >= 2 ? genericType[1] : null), null, subKey, json.get(subKey)));
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
|
@ -170,7 +171,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
|
|||
}
|
||||
|
||||
|
||||
protected Object readObject(Class<?> type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, NoSuchFieldException {
|
||||
protected Object readObject(Class<?> type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException {
|
||||
// Only parse if json is a map
|
||||
if (json == null || !json.isMap())
|
||||
return null;
|
||||
|
|
@ -182,17 +183,17 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
|
|||
Object obj;
|
||||
// Try using explicit class
|
||||
if (type != null) {
|
||||
obj = type.newInstance();
|
||||
obj = type.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
// Try using metadata
|
||||
else if (json.getString(MD_CLASS) != null) {
|
||||
Class<?> objClass = Class.forName(json.getString(MD_CLASS));
|
||||
obj = objClass.newInstance();
|
||||
obj = objClass.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
// Search for registered classes
|
||||
else if (registeredClasses.containsKey(key)) {
|
||||
Class<?> objClass = registeredClasses.get(key);
|
||||
obj = objClass.newInstance();
|
||||
obj = objClass.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
// Unknown class
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ import java.io.*;
|
|||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static zutil.parser.json.JSONObjectInputStream.MD_CLASS;
|
||||
|
|
@ -101,6 +101,9 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
|
|||
ClassUtil.isWrapper(obj.getClass())) {
|
||||
root = getPrimitiveDataNode(obj.getClass(), obj);
|
||||
}
|
||||
else if (obj.getClass().isEnum()) {
|
||||
root = getPrimitiveDataNode(String.class, obj.toString());
|
||||
}
|
||||
// Add an array
|
||||
else if (objClass.isArray()) {
|
||||
// Special case for byte arrays
|
||||
|
|
@ -117,9 +120,9 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
|
|||
}
|
||||
}
|
||||
// List
|
||||
else if (List.class.isAssignableFrom(objClass)) {
|
||||
else if (Collection.class.isAssignableFrom(objClass)) {
|
||||
root = new DataNode(DataNode.DataType.List);
|
||||
List list = (List)obj;
|
||||
Collection<?> list = (Collection<?>) obj;
|
||||
for (Object item : list) {
|
||||
root.add(getDataNode(item));
|
||||
}
|
||||
|
|
@ -127,7 +130,7 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
|
|||
// Map
|
||||
else if (Map.class.isAssignableFrom(objClass)) {
|
||||
root = new DataNode(DataNode.DataType.Map);
|
||||
Map map = (Map)obj;
|
||||
Map<?, ?> map = (Map<?, ?>) obj;
|
||||
for (Object key : map.keySet()) {
|
||||
root.set(
|
||||
getDataNode(key).getString(),
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public class JSONSerializerTest{
|
|||
assertThat(data, containsString("'str': 'abcd'"));
|
||||
assertThat(data, containsString("'value': 42"));
|
||||
assertThat(data, containsString("'decimal': 1.1"));
|
||||
assertThat(data, containsString("'testEnum': 'ENUM2'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -207,18 +208,24 @@ public class JSONSerializerTest{
|
|||
|
||||
/******************** Test Classes ************************************/
|
||||
|
||||
public enum TestEnum {
|
||||
ENUM1, ENUM2, ENUM3
|
||||
}
|
||||
|
||||
public static class TestClass implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
String str;
|
||||
double decimal;
|
||||
TestObj obj1;
|
||||
TestObj obj2;
|
||||
TestEnum testEnum;
|
||||
|
||||
public TestClass init() {
|
||||
this.str = "abcd";
|
||||
this.decimal = 1.1;
|
||||
this.obj1 = new TestObj().init();
|
||||
this.obj2 = new TestObj().init();
|
||||
this.testEnum = TestEnum.ENUM2;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -227,6 +234,7 @@ public class JSONSerializerTest{
|
|||
Assert.assertEquals(obj1.decimal, obj2.decimal, 0.001);
|
||||
Assert.assertEquals(obj1.obj1, obj2.obj1);
|
||||
Assert.assertEquals(obj1.obj2, obj2.obj2);
|
||||
Assert.assertEquals(obj1.testEnum, obj2.testEnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue