深入学习java源码之Map转Object与json转Object
org.apache.commons.beanutils.PropertyUtils
一般情况下,在Java中你可以通过get方法轻松获取beans中的属性值。但是,当你事先不知道beans的类型或者将要访问或修改的属性名时,该怎么办?Java语言中提供了一些像java.beans.Introspector
这 样类,实现了在运行时检测Java类并确定属性get和set方法的名称,结合Java中的反射机制就可以调用这些方法了。然而,这些APIs使用起来比 较困难,并且将Java类中一些不必要的底层结构暴露给了开发人员。BeanUtils包中的APIs试图简化动态获取和设置bean属性的过程。
Bean Utility就是Bean小工具,主要是封装了反射(reflection)和自省(introspection)的API(可以查看java.lang.reflect和java.beans文档),对bean进行操作。
操作Bean的属性,针对Bean属性排序,Bean和Map的转换,创建动态的Bean等
使用缺点,当两个不同的类A 类B有相同的字段名称,若类A的类型为 string,类B的类型为Integer,这里会报错。这种情况若要支持需要做特殊处理。
利用反射操作bean的属性
getSimpleProperty()通过反射读取属性
Person person=newPerson();
person.setName=("heis");
String name=(String)PropertyUtils.getSimpleProperty(person,"name");->heis
Employee employee = ...;
String firstName = (String) PropertyUtils.getSimpleProperty(employee, "firstName");
String lastName = (String) PropertyUtils.getSimpleProperty(employee, "lastName");
... manipulate the values ...
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);
getNestedProperty()检索嵌套的bean属性
Book book=newBook();
book.setAuthor(person);
String authorName=(String)PropertyUtils.getNestedProperty(book,"author.name");//得到person的name
getIndexedProperty()访问数组或List型内Object的属性
对于indexed(索引)属性,你有两种选择 - 你既可以在属性名后面添加方括号在里面放上一个下标,也可以在调用方法时将其作为一个独立参数:
Chapter chapter1=newChapter();
Chapter chapter2=newChapter();
book.getChapters().add(chapter1);
book.getChapters().add(chapter2);
Chapter chapter=(Chapter)PropertyUtils.getIndexedProperty(book,"chapter[0]");
属性名的下标只能是整数常量。如果你想获取的项的索引是计算出来的,你可以将属性名和索引作为字符串组合起来。例如,你可以向下面这样做:
Employee employee = ...;
int index = ...;
String name = "subordinate[" + index + "]";
Employee subordinate = (Employee) PropertyUtils.getIndexedProperty(employee, name);
Employee employee = ...;
int index = ...;
Employee subordinate = (Employee) PropertyUtils.getIndexedProperty(employee, "subordinate", index);
getMappedProperty()访问Map型bean属性的值
类似的,获取和设置mapped(映射)属性的方法同样有两对。与indexed(索引)不同的是额外的属性是用括号括起来的(“(”和“)”)而不是方括号,并且获取和设置值时如同从底层的map中获取和设置值一样。
Person person=newPerson();
person.setName=("heis");
Map favorites=newHashMap();
favorites.put("food","rice");
person.setFavorite(favorites);
String favorFood=(String)PropertyUtils.getMappedProperty(person,"favorites(food)");->rice
你可以使用下面两种方法设置employee的家庭住址:
Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address(home)", address);
Employee employee = ...;
Address address = ...;
PropertyUtils.setMappedProperty(employee, "address", "home", address);
getProperty()和setProperty()可以访问任何bean属性,通过表达式可以完成上面方法的功能
访问嵌套属性 在上面的例子中,我们假设你将bean作为第一个参数传入PropertyUtils方法,并希望获取指定属性的值。然而,如果属性的值是一个Java对象,并且你希望进一步获取这个Java对象的某个属性的值?
例如,假设你事实上想要获取的值是employee家庭住址中的city属性。使用标准的Java编程技术直接获取bean的对应属性,你可以这样写:
String city = employee.getAddress("home").getCity();
使用PropertyUtils类中的等效机制被称为嵌套属性访问。使用这种方法,你将访问路径上的属性的名称用“.”拼接起来 --与你在JavaScript执行嵌套属性访问的方式非常相似。
PropertyUtils中等效于上面的Java代码将是这样:
String city = (String) PropertyUtils.getNestedProperty(employee, "address(home).city");
最后,方便起见,PropertyUtils提供了如下一组方法,它们接收simple、indexed和mapped属性的任意组合方法,支持任意层次的嵌套:
Employee employee = ...;
String city = (String) PropertyUtils.getProperty(employee,"subordinate[3].address(home).city");
isReadable()和isWritable()检查bean是否可读(有getter)或可写(有setter)
PropertyUtils.isReadable(book,"name");
PropertyUtils.isWritable(book,"name");
getPropertyType()获取属性类型
System.out.println(PropertyUtils.getPropertyType(person,"favorites"));->java.util.Map
copyProperty()复制Bean属性,只复制引用,final类型和原始类型(primitive type)
BeanUtils和PropertyUtils复制对象时,根据属性名进行复制。
如果属性名相同,但类型不同,BeanUtils会直接转换。而PropertyUtils会直接抛出异常。
Book book1=newBook();
book1.setName("Commons Cookbook Notes");
Book book2=newBook();
PropertyUtils.copyProperty(book2,book1);//将book1的name属性copy到book2
public class User {
private String userName;
private String password;
private Integer age;
private Float d;
}
public class ToUser {
private String userName;
private String password;
private Integer age;
private String d;
}
package com.test;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
public class CopyClass {
public static void main(String[] args) {
User u1 = new User();
u1.setAge(10);
u1.setPassword("22222");
u1.setUserName("王黄");
u1.setD(1.0f);
ToUser u2 = new ToUser();
try {
BeanUtils.copyProperties(u2, u1);
//PropertyUtils.copyProperties(u2, u1);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(u1.getD().getClass());
System.out.println(u2.getD().getClass());
}
}
describe()创建包含Bean属性的Map
Person person=newPerson();
person.setName("heis");
Book book=newBook();
book.setName("Commons Cookbook Notes");
book.setAuthor(person);
Map propMap=PropertyUtils.describe(book);
propMap.get("name");->Commons Cookbook Notes
propMap.get("author");->person
java源码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
/**
* 通用反射处理类
*/
public class BeanUtils {
/**
* copy 对象属性
* @param target
* @param src
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static void copyProperties(Object target, Object src) throws Exception {
if (target instanceof Map) {
Map targetMap = (Map) target;
if (src instanceof Map) {
targetMap.putAll((Map)src);
} else
targetMap.putAll(PropertyUtils.describe(src));
} else{
org.apache.commons.beanutils.BeanUtils.copyProperties(target, src);
}
}
/**
* pojo 对象转换成 数据库Map对象
* @param paramMap
* @param obj
* @throws Exception
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void beanToMap(Map paramMap, Object obj) throws Exception {
BeanUtils.copyProperties(paramMap, obj);
MapUtil.removeKeys(paramMap,new String []{"class"});
Iterator it = paramMap.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
Object value = paramMap.get(key);
if (value != null) {
String clsName = value.getClass().getName();
if(clsName.indexOf("com.cnten") > -1) {
Map subParamMap = new HashMap();
beanToMap(subParamMap, value);
paramMap.put(key, subParamMap);
}else if(value instanceof List){
List listVal = (List)value;
List subArrList = new ArrayList();
for (int i = 0; i < listVal.size(); i++) {
Object pvalue = listVal.get(i);
clsName = pvalue.getClass().getName();
if(clsName.indexOf("com.cnten") > -1) {
Map subParamMap = new HashMap();
beanToMap(subParamMap, pvalue);
subArrList.add(subParamMap);
}else{
subArrList.add(pvalue);
}
}
paramMap.put(key, subArrList);
}
}
}
}
/**
*
* bean转换为json
* @param src
* @return
*/
public static String beanToJson(T src){
SerializerFeature[] features = { SerializerFeature.WriteMapNullValue, // 输出空置字段
SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null
SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null
SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null
SerializerFeature.WriteNullStringAsEmpty, // 字符类型字段如果为null,输出为"",而不是null
SerializerFeature.WriteClassName,
};
return JSON.toJSONString(src,features);
}
/**
* json转为Bean
* @param
* @param json
* @param clazz
* @return
*/
public static T jsonToBean(String json,Class clazz){
return JSON.parseObject(json, clazz);
}
/**
* bean转换为json
* @param src
* @return
*/
public static String beanToJsonNCls(T src){
SerializerFeature[] features = { SerializerFeature.WriteMapNullValue, // 输出空置字段
SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null
SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null
SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null
SerializerFeature.WriteNullStringAsEmpty, // 字符类型字段如果为null,输出为"",而不是null
};
return JSON.toJSONString(src,features);
}
}
import java.util.Map;
public class PerBeanUtils extends BeanUtils {
@SuppressWarnings("unchecked")
public static T mapToObject(Map map, Class beanClass) throws Exception {
if (map == null)
return null;
Object obj = beanClass.newInstance();
org.apache.commons.beanutils.BeanUtils.populate(obj, map);
return (T)obj;
}
public static Map objectToMap(Object obj) {
if(obj == null)
return null;
return new org.apache.commons.beanutils.BeanMap(obj);
}
}
使用
List dataList = new ArrayList();
for (LinkedHashMap linkedHashMap : dataList) {
try {
pipeVO = PerBeanUtils.mapToObject(linkedHashMap, getEntityClass());
} catch (Exception e) {
logger.error(MessageFormat.format("", ruleCode),e);
continue;
}
if(pipeVO!=null){
dataList.add(pipeVO);
}
}
public Class getEntityClass() {
Class _class = null;
try {
_class = Class.forName(p.getModeClass());
} catch (ClassNotFoundException e) {
e.printStackTrace();
logger.error(MessageFormat.format("", ruleCode),e);
}
return _class;
}