Android(Java)Bean自动转换为map的方法

原创声明: 该文章为原创文章,未经博主同意严禁转载。

在开发Android的时候,用户端与服务端一般是通过传递Json数据的方式进行通信的,目前主流都是使用Gson库对Json数据进行处理但实际开发的时候,Gson库不一定能满足我们的需求。例如,我曾经做过一个项目,服务器以Json的格式发送数据到客户端,而客户端需要以Map类型的数据回传给服务器。所以在这个时候,我们就需要把Bean类以类似Gson库的方式自动转换成Map数据,以达到提高效率的目的。

创建能自动解析数据的基类BaseBean

该类中只有一个方法,就是toMap。toMap方法的作用是通过class.getDeclaredFields()方法获取class对象的所有属性,然后将属性名转化为map对象的key,属性的值转化为map对象的value。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class BaseBean {
private Map<String, Object> params;
/**
* @Method: toMap()
* @author create by Tang
* @date date 16/8/23 下午3:20
* @Description: 把实体类转换成Map类
*/
public Map<String,Object> toMap() {
Class<? extends Object> clazz = this.getClass();
Class<? extends Object> superClass = clazz.getSuperclass();
Field[] fields = clazz.getDeclaredFields();
Field[] superFields = superClass.getDeclaredFields();
if (fields == null || fields.length == 0 ){
return Collections.EMPTY_MAP;
}
params = new HashMap<>();
try {
for (Field field : fields) {
field.setAccessible(true);
if (field.get(this) != null){
ParamsName paramsName = field.getAnnotation(ParamsName.class);
String key;
if (paramsName == null){
key = field.getName();
}else {
key = paramsName.value();
}
if (field.get(this) != null){
params.put(key , String.valueOf(field.get(this)));
}else {
params.put(key, "null");
}
}
}
for (Field superField : superFields){
if (superField.get(this) != null){
superField.setAccessible(true);
ParamsName superParamsName = superField.getAnnotation(ParamsName.class);
String superKey;
if (superParamsName == null){
superKey = superField.getName();
}else {
superKey = superParamsName.value();
}
if (superField.get(this) != null){
params.put(superKey, String.valueOf(superField.get(this)));
}else {
params.put(superKey, "null");
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return params;
}
public String toString(){
if (params == null) {
return "null";
}
return params.toString();
}
}

上面代码中class就是我们传递进来需要转换成map的Bean基类,superClass则是该类的父类。获取class的父类是由于class.getDeclaredFields方法只能获取自身的属性,而无法获得父类的属性,所以需要获取class对象的父类。
从上面的代码可以看出,将java实体类转换成map对象的方法很简单。通过遍历获得的Field对象,并通过Field.getName方法获取属性的命名作为map对象的key,通过Field.get(class)方法获取属性的值即可。
注 : field.setAccessible(true)的作用是允许获取私有变量。

细心读者可能会发现,有时候我们实体类的命名和服务器发给我们的命名规则是不一样的。但是我们又不想修改属性名的情况下怎么办?Gson库提供给我们的方法是通过注解的方式(@SerializedName)实现对属性的重命名。那么如果我们自定义的Gmap类能不能也实现该功能呢?答案当然是可以的。

通过查看Gson的源码,我们发现Gson实现通过注解对属性进行重命名的方法实际是比较简单的。下面我们来详细看下注解是如何实现属性的重命名的。

通过注解实现属性重命名

先看代码:

注解的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface ParamsName {
/**
* @Method: value()
* @author create by Tang
* @date date 16/8/23 下午3:55
* @Description:
* 返回Map的key Name,默认为参数名
*/
String value();
}

在Map类中通过获取属性的注解对map的key实现重命名的方法:

1
2
3
4
5
6
7
8
9
10
11
12
ParamsName paramsName = field.getAnnotation(ParamsName.class);
String key;
if (paramsName == null){
key = field.getName();
}else {
key = paramsName.value();
}
if (field.get(this) != null){
params.put(key , String.valueOf(field.get(this)));
}else {
params.put(key, "null");
}

注解的定义很简单,就是常规的java注解的定义。代码的实现也比较简单,通过field.getAnnotation(class)方法获得属性的注解,然后对获得的注解进行判断,如果注解值为空,则返回属性的实际名称,如果注解不为空,则返回注解的值。

使用方法

使用方法很简单,在创建bean类(或需要转化为map数据的类)时继承BaseBean即可,然后在需要的时候调用toMap()方法即可。

小结

以上就是我实现的把java bean类自动转化为map数据的方法。这个方法有个缺点,由于使用了反射的方法每次转化的时候会对java类遍历一次,所以这个方法会影响程序运行的性能。在查看Gson库的源码的时候,我发现Gson有更好的实现方法。具体我会在下一篇文章深度剖析Gson是如何在不影响效率的情况下实现数据的转化的。