说明:
工具类主要针对DAO层无映射框架便捷转换实体,也适用于jdk1.6以上版本,当然6以上可用的转化方法很多,这里不再赘述,随便举一个栗子
String str = "[{name:'name1',value:'value1'},{name:'name2',value:'value2'},{name:'name3',value:'value3'}]" ;
JJSONArray json = JSONArray.fromObject(str ); // 将字符串转成 JSONArray 对象
List<User> list = JsonUtils.getCollectionList(jsonArray.toString(), User.class);
//JsonUtils 工具类
public static <T> T getCollectionList(String jsonStr, Class<?> parameterClasses) {
ObjectMapper mapper = new ObjectMapper();
JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, parameterClasses);
return toJSONObj(jsonStr, javaType);
}
public static <T> T toJSONObj(String jsonString, JavaType javaType) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
T obj = null;
try {
obj = objectMapper.readValue(jsonString, javaType);
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
下面的工具类鸡肋的地方:
数组元素的顺序必须和实体类中的成员变量顺序保持一致,数组元素(即sql中字段个数)小于实体成员变量个数会报错;
文章也借鉴了一些大牛给出来的反射中的问题的解决方案!
1.传入数据集合和实体类,对比元素个数,利用反射给对象赋值并放入集合中,如
List<Object[]> arrList=dao.getList();
List<User> list= castEntity(arrList, User.class); //数据格式是
[{"1","java"},{"2","C++"}]; 有别于上述的键值对的json字符串
属性描述器设值 PropertyDescriptor 是关键,在不确定类和属性值情况使用,可以简化很多代码
/**
*
*<p><strong>Description:将数组数据转换为自定义实体类,
* 数组元素的顺序必须和实体类中的成员变量顺序保持一致,数组元素不能小于实体属性个数;
* </strong></p>
* @param list 数组集合
* @param clazz 实体类
* @return 自定义的实体集合
*/
public static <T> List<T> castEntity(List<Object[]> list, Class<T> clazz) {
List<T> returnList = new ArrayList<T>();
if (list==null||list.isEmpty()) {
return returnList;
}
//获取集合中每个数组的元素个数
Object[] co = list.get(0);
try {
//获取vo中的所有属性
Field[] fields = clazz.getDeclaredFields();
//如果数组集合元素个数与实体类成员变量个数不一致则发生错误
if (fields.length < co.length) {
log.info("实体成员变量个数小于结果数组元素个数,仅转换数组元素[0-"+(fields.length-1)+"]的数据");
}else if(fields.length > co.length){
log.error("异常:不允许实体成员变量个数大于结果数组元素个数");
throw new Exception("不允许实体成员变量个数大于结果数组元素个数");
}
for (int i = 0; i < list.size(); i++) {
Object[] array = list.get(i);
T instance = clazz.newInstance();
for (int j = 0; j < fields.length; j++) {
Field field=fields[j];
//根据成员变量名设置属性描述器
PropertyDescriptor pd = new PropertyDescriptor(field.getName(),clazz);
//获取setter方法
Method method = pd.getWriteMethod();
if (method != null) {
if(array[j]==null||"".equals(array[j])){
continue;
}
//调用setter方法,给成员变量赋值
method.invoke(instance,convert(field,array[j]));
}
}
returnList.add(instance);
}
} catch (Exception e) {
log.error("实体数据转化为实体类发生异常:异常信息",e);
return returnList;
}
return returnList;
}
2.将数组元素转换为类中对应的参数类型(看起来有点low,jdk6我只能发挥到这里,有好的方法,请大牛们不吝赐教),1.7可用 switch 稍微优雅一点,1.8可以用lambda表达式 消除 if else,这里不做展开
/**
*
*<p><strong>Description:将数组元素转换为类中对应的参数类型</strong></p>
* @param field 成员变量
* @param obj 数组元素
* @return 对应数据类型
* @throws Exception
*/
public static Object convert(Field field, Object obj) throws Exception{
Class<?> type = field.getType();
//转换参数类型
if(type == String.class){
return String.valueOf(obj);
}else if(type.equals(Long.class)){
return Long.valueOf(obj.toString());
}else if(type.equals(Integer.class)){
return Integer.valueOf(obj.toString());
}else if(type.equals(Float.class)){
return Float.valueOf(obj.toString());
}else if(type.equals(Double.class)){
return Double.valueOf(obj.toString());
}else if(type.equals(Short.class)){
return Short.valueOf(obj.toString());
}else if(type.equals(Byte.class)){
return Byte.valueOf(obj.toString());
}else if(type.equals(BigDecimal.class)){
return new BigDecimal(obj.toString());
}else if(type.equals(Character.class)){
return Character.valueOf(obj.toString().charAt(0));
}else if(type.equals(Date.class)){
return DateUtil.getStringToDate(obj.toString(), "yyyy-MM-dd HH:mm:ss.SSS");
}else if(type.equals(Boolean.class)){
return Boolean.valueOf(obj.toString());
}else{
throw new Exception("不存在对应的参数类型");
}
}
}
3.引用jar
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import org.apache.log4j.Logger;