通过反射实现
过程并无甚复杂,通过反射实现接口。首先当然是遍历一下这些集合,无论 Map 还是 Bean。
/**
* Bean 转换为 Map
* @param obj
* @return
*/
public static Map<String, Object> bean2map(Object obj) {
if (obj == null)
return null;
Map<String, Object> map = new HashMap<>();
for (Method method : obj.getClass().getMethods()) {
String methodName = method.getName();
if (methodName.startsWith("get")) {
Object value = executeMethod(obj, method); // 反射获取值
if (value != null)
map.put(getFieldName(methodName, "get"), value);
}
}
return map;
}
/**
* 调用方法,方法没有参数的
*
* @param instance
* 对象实例,bean
* @param method
* 方法对象
* @return 执行结果
*/
public static Object executeMethod(Object instance, Method method) {
try {
return method.invoke(instance);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
return null;
}
}
/**
* 根据方法名称来截取属性名称
* @param methodName
* 方法名称
* @param action
* set|get
* @return
*/
public static String getFieldName(String methodName, String action) {
methodName = methodName.replace(action, "");
return Character.toString(methodName.charAt(0)).toLowerCase() + methodName.substring(1);
}
对应地,就有 Map 转换为 Bean。
/**
* Map 转换为 Bean
*
* @param map
* @param obj
*/
public static void map2bean(Map<String, Object> map, Object obj) {
if (obj != null || map != null)
return null;
for (Method method : obj.getClass().getMethods()) {
String methodName = method.getName();
if (methodName.startsWith("set")) {
methodName = getFieldName(methodName, "set");
if (map.containsKey(methodName))
executeMethod(obj, method, map.get(methodName));
}
}
}
/**
* 调用方法
*
* @param instance
* 对象实例,bean
* @param method
* 方法对象
* @param args
* 参数列表
* @return 执行结果
*/
public static Object executeMethod(Object instance, Method method, Object... args) {
try {
return method.invoke(instance, args);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
return null;
}
}
将 map 中数据填入到 obj 中。obj 是 POJO。 如果 POJO 有这个 setter,那就根据 setter 中 setXxx 获取 xxx,作为 map 的 key 读取 map 的那個 value。
Object 2 Bean Value
bean2map 过程中,值放到 map 中没类型转换的问题,因为 map 的范型是 <String, Object>,这时 map 好比 O 型血,什么都是用它,但反之 map2bean 则不然 bean 的 setter方法是有类型要求的,因此你传入 Object 的参数并不一定能匹配。如果不转换很容易会出现 java.lang.IllegalArgumentException: argument type mismatch 的异常。于是我们类构建更复杂的 map2bean 函数,让类型差不多的也能通过转换,转变为真正符合类型要求的类型。
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.ajaxjs.util.DateTools;
import com.ajaxjs.util.LogHelper;
import com.ajaxjs.util.reflect.BeanUtil;
import com.ajaxjs.util.reflect.Reflect;
import com.ajaxjs.util.reflect.ReflectNewInstance;
/**
* 将 map 数据通过反射保存到 pojo(bean) 中。
*
* @author frank
*
* @param <T>
* 实体类型
*/
public class Map2Pojo<T> extends BeanUtil {
private static final LogHelper LOGGER = LogHelper.getLog(Map2Pojo.class);
/**
* 实体类型类对象
*/
private Class<T> pojoClz;
/**
* 用于数组的分隔符
*/
private char diver = ',';
/**
*
* @param pojoClz
* 实体类型类对象
*/
public Map2Pojo(Class<T> pojoClz) {
this.pojoClz = pojoClz;
}
/**
* 把单个原始数据 map 转换为单个实体
*
* @param map
* 原始数据
* @param pojo
* 实体
* @param fields
* 反射出来的字段信息
*/
private T map2pojo(Map<String, Object> map, List<Field> fields) {
T pojo = ReflectNewInstance.newInstance(pojoClz);
if(pojo == null) return null;
for (Field f : fields) {
String key = f.getName(); // 字段名称
Class<?> t = f.getType(); // 字段期望的类型
Object value = map.get(key);
if (value != null) {
// System.out.println(key + ":" + map.get(key).getClass().getName());
String methodName = "set" + firstLetterUpper(key);
if (t == boolean.class) {
// System.out.println("methodName:::::" + methodName);
// 布尔型
methodName = key.replace("is", "");
methodName = "set" + firstLetterUpper(methodName);
// System.out.println("methodName:::::" + "set" + Reflect.firstLetterUpper(methodName));
if(value instanceof String) {
value = (String)value;
if(value.equals("yes") || value.equals("true") || value.equals("1")) {
value = true;
}
if(value.equals("no") || value.equals("false") || value.equals("0")) {
value = false;
}
}
executeMethod(pojo, methodName, t, (boolean) value);
} else if (t == int.class || t == Integer.class) {
if(value.getClass() == String.class)
value = Integer.parseInt(value.toString());
// 整形
executeMethod(pojo, methodName, t, value);
} else if (t == int[].class || t == Integer[].class) {
// 复数
if (value instanceof String) {
int[] intArr = strArr2intArr(value);
executeMethod(pojo, methodName, t, intArr);
} else {
LOGGER.info("what's this!!? " + value);
}
} else if (t == String.class) {
// 字符型
Reflect.executeMethod(pojo, methodName, t, value.toString());
} else if (t == String[].class) {
// 复数
if (value instanceof String[]) {
Reflect.executeMethod(pojo, methodName, t, value);
} else if (value instanceof ArrayList) {
@SuppressWarnings("unchecked")
ArrayList<String> list = (ArrayList<String>) value;
String[] arr = new String[list.size()];
executeMethod(pojo, methodName, t, list.toArray(arr));
} else if (value instanceof String) {
String str = (String) value;
executeMethod(pojo, methodName, t, str.split(getDiver() + ""));
} else {
LOGGER.info("what's this!!?" + value.getClass().getName());
}
} else if (t == long.class || t == Long.class) {
// LONG 型
executeMethod(pojo, methodName, t, Long.valueOf(value.toString()));
} else if (t == Date.class) {
if (value instanceof java.sql.Timestamp) {
long time = ((java.sql.Timestamp) value).getTime();
executeMethod(pojo, methodName, t, new Date(time));
} else {
executeMethod(pojo, methodName, t, DateTools.Objet2Date(value));
}
} else {
// System.out.println("------------" + t.getName());
executeMethod(pojo, methodName, value);
}
}
}
return pojo;
}
/**
* '["1", "2", ...]' --> [1, 2, ...]
* @param value
* @return
*/
private int[] strArr2intArr(Object value) {
String str = (String) value;
// 当它们每一个都是数字的字符串形式
String[] strArr = str.split(getDiver() + "");
int[] intArr = new int[strArr.length];
for (int i = 0; i < strArr.length; i++)
intArr[i] = Integer.parseInt(strArr[i]);
return intArr;
}
/**
* 把原始数据 map 转换为实体
*
* @param maps
* 原始数据
* @param fields
* 反射出来的字段信息
* @return 转换后的实体列表
*/
// public List<T> map2pojo(List<Map<String, Object>> maps, List<Field> fields) {
// List<T> list = new ArrayList<>();
T[] a = (T[])java.lang.reflect.Array.newInstance(pojoClz, maps.size());
list.toArray(T[]);
//
// for (Map<String, Object> map : maps)
// list.add(map2pojo(map, fields));
//
// return list;
// }
/**
* 把原始数据 maps 转换为实体
*
* @param maps
* 原始数据
* @return 转换后的实体列表
*/
public List<T> map2pojo(List<Map<String, Object>> maps) {
List<Field> fields = getDeclaredField(pojoClz);
List<T> list = new ArrayList<>();
// T[] a = (T[])java.lang.reflect.Array.newInstance(pojoClz, maps.size());
// list.toArray(T[]);
for (Map<String, Object> map : maps)
list.add(map2pojo(map, fields));
return list;
// return map2pojo(maps, Reflect.getDeclaredField(pojoClz));
}
/**
* 把原始数据 map 转换为实体
*
* @param map
* 原始数据
* @return 转换后的实体
*/
public T map2pojo(Map<String, Object> map) {
return map2pojo(map, getDeclaredField(pojoClz));
}
/**
* @return {@link #diver}
*/
public char getDiver() {
return diver;
}
/**
* @param diver {@link #diver}
*/
public void setDiver(char diver) {
this.diver = diver;
}
}
通过 Bean 内省实现
后来发现反射性能不是很好,于是我们试试 Java Bean 的内省功能也可以转换。
/**
* map 转实体
*
* @param map
* @param clz
* 实体类
* @return 实体 bean 对象
*/
public static <T> T map2Bean(Map<String, Object> map, Class<T> clz) {
T bean = ReflectNewInstance.newInstance(clz);
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clz);
for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
String key = property.getName();
if (map.containsKey(key)) {
Object value = map.get(key);
// 得到property对应的setter方法
Method setter = property.getWriteMethod();
setter.invoke(bean, value);
}
}
} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return bean;
}
/**
* Bean 转为 Map
*
* @param bean
* 实体 bean 对象
* @return
*/
public static <T> Map<String, Object> bean2Map(T bean) {
Map<String, Object> map = new HashMap<String, Object>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
String key = property.getName();
// 过滤 class 属性
if (!key.equals("class")) {
// 得到 property 对应的 getter 方法
Method getter = property.getReadMethod();
Object value = getter.invoke(bean);
map.put(key, value);
}
}
} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return map;
}