先放一段代码
public class Test {
public static void main(String[] args) {
//建立一个数组 第一个放入child 第二个放入parent
List list = new ArrayList<>();
Parent parent = new Parent();
parent.setX("1");
Child child = new Child();
child.setX1("1");
list.add(child);
list.add(parent);
String json = JSON.toJSONString(list);
List list1 = JSON.parseArray(json, Parent.class);
//强转失败
Child child1 = (Child) list1.get(0);
}
}
显然List 里放入多种子类的话 子类类型会丢失 但是项目里有时候会有需求要把子类的信息完整得还原出来
实现思路如下: 在父类的最顶层里加一个classInfo,去标明类信息,子类都继承这个父类,然后序列化的时候拿map去接收 最后将map
当做一颗树 ,map如果带classInfo 就将他转化成classInfo的类,如果map里面还有map同理,层层递归
当然要考虑对象循环引用不能死递归的问题:
如果这个map已经被转成对象 那么他会被记在map里key是map value是map对应的对象
循环引用时取对象的hashcode会报错,所以用map当key会栈溢出 (最后放栈溢出的代码)
所以用System.identityHashCode(map) (可以看作map的内存地址)来当key
核心代码如下
/**
* 对参数做树递归 有条件用栈做
*
* @param object
* @param remember
* @return
*/
private static Object map2Class(Object object, Map remember) {
if (object instanceof List) {
List obj = new ArrayList();
List list = (List) object;
list.forEach(i -> {
obj.add(map2Class(i, remember));
});
return obj;
} else if (object instanceof Map) {
Map map = (Map) object;
Object classInfo = map.remove("className");
Object o = null;
if (classInfo == null) {
return Optional.ofNullable(remember.get(System.identityHashCode(map))).orElseGet(
() -> {
for (Map.Entry entry : map.entrySet()) {
map.put(entry.getKey(), map2Class(entry.getValue()));
}
return map;
}
);
} else {
try {
Class> aClass = Class.forName(classInfo.toString());
o = aClass.getDeclaredConstructor().newInstance();
remember.put(System.identityHashCode(map), o);
} catch (Exception e) {
e.printStackTrace();
}
}
for (Map.Entry entry : map.entrySet()) {
if (entry.getValue() != null) {
Object o1 = map2Class(entry.getValue(), remember);
reflectUtil.setProperty(o, entry.getKey(), o1);
}
}
return o;
} else {
return object;
}
}
/**
* 调用类
* @param object
* @param
* @return
*/
public static T map2Class(Object object) {
Map map = new HashMap<>();
Object o = map2Class(object, map);
return (T) o;
}
map入参如下:
转化后
栈溢出的代码如下:
public static void main(String[] args) {
Map map=new HashMap<>();
Map map1=new HashMap<>();
map.put("1",map1);
map1.put("1",map);
Set
反射工具类代码 对时间做了下特殊处理 缓存了反射的方法信息
public class GetSetterReflectUtil {
private final static Logger logger = LoggerFactory.getLogger(GetSetterReflectUtil.class);
private static WeakHashMap, Map>> methodWeakHashMap = new WeakHashMap<>();
private static Map> classFunctionMap = new HashMap<>();
static {
classFunctionMap.put(Date.class, (o) -> {
if (o instanceof Long) {
o = new Date((Long) o);
}
if (o instanceof String) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
Date parse = null;
try {
parse = sdf.parse(o.toString());
return parse;
} catch (ParseException e) {
logger.error("时间转化出现错误 格式不匹配 value[{}]", o);
}
}
return o;
});
}
private static Map> getClassMethod(Object beanObj) {
Class> aClass = beanObj.getClass();
String clazzName = aClass.getName();
PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(beanObj.getClass());
Map> map = new HashMap<>();
for (PropertyDescriptor descriptor : propertyDescriptors) {
String name = descriptor.getName();
Method readMethod = descriptor.getReadMethod();
Method writeMethod = descriptor.getWriteMethod();
map.put(name, Tuple3.of(descriptor.getPropertyType(), readMethod, writeMethod));
}
SoftReference softReference = new SoftReference(clazzName);
methodWeakHashMap.put(softReference, map);
return map;
}
public Object invokeMethod(Object beanObj, String methodName, String type, Object param) {
Class> aClass = beanObj.getClass();
String clazzName = aClass.getName();
SoftReference softReference = new SoftReference(clazzName);
Map> methodMap = methodWeakHashMap.get(softReference);
if (methodMap == null) {
methodMap = getClassMethod(beanObj);
methodWeakHashMap.put(softReference, methodMap);
}
Tuple3 tuple3 = methodMap.get(methodName);
try {
Method method = "R".equals(type) ? tuple3.getT() : tuple3.getValue();
if (method == null) {
logger.error("未找到 name=[{}]的方法", methodName);
} else {
method.setAccessible(true);
Function