谷歌GSON这个Java类库可以把Java对象转换成JSON,也可以把JSON字符串转换成一个相等的Java对象。Gson支持任意复杂Java对象包括没有源代码的对象。
网上有很多网友测试等出结论:bean和json之间不管哪种转换方式,性能都一样,如下:
Jackson > Gson > Json-lib
因本人更熟悉Gson,且Gson和其他现有java json类库最大的不同是Gson需要序列化得实体类不需要使用annotation来标识需要序列化得字段,同时Gson又可以通过使用annotation来灵活配置需要序列化的字段。
下面是一个简单的例子:
首先定义一个注解:
package com.gson.dalin.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Date:2015/05/27
* @author dalin
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FieldComment {
String value();
}
需要操作的目标Bean
package com.gson.dalin;
import java.util.Date;
import com.google.gson.annotations.Expose;
import com.gson.dalin.annotation.FieldComment;
/**
* Date:2015/05/27
* @author dalin
*
*/
public class MyEntity {
@Expose
@FieldComment("用户ID")
private long id;
@Expose
@FieldComment("用户名")
private String userName;
private String address;
private Date date;
private MySuperEntity entity;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public MySuperEntity getEntity() {
return entity;
}
public void setEntity(MySuperEntity entity) {
this.entity = entity;
}
}
目标Bean中的属性对象:
package com.gson.dalin;
import java.util.Date;
/**
* Date:2015/05/27
* @author dalin
*
*/
public class MySuperEntity {
private long id;
private String name;
private Date date;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
</pre></p><p>序列化类:</p><p><pre name="code" class="java">package com.gson.dalin;
import java.util.Date;
import com.google.gson.Gson;
/**
* Date:2015/05/27
* @author dalin
*
*/
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Gson gson = new Gson();
MyEntity entity = new MyEntity();
entity.setId(123456L);
entity.setUserName("Test User");
entity.setAddress("金茂中路");
entity.setDate(new Date());
String json = gson.toJson(entity);
System.out.println("Using Expose:" + json);
}
}
结果:Using Expose:{"id":123456,"userName":"Test User","address":"金茂中路","date":"May 27, 2015 9:54:44 PM"}
另一种序列化方式:
package com.gson.dalin;
import java.util.Date;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Date:2015/05/27
* @author dalin
*
*/
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
MyEntity entity = new MyEntity();
entity.setId(123456L);
entity.setUserName("Test User");
entity.setAddress("金茂中路");
entity.setDate(new Date());
String json = gson.toJson(entity);
System.out.println("Unusing Expose:" + json);
}
}
结果:Unusing Expose:{"id":123456,"userName":"Test User"}
由以上两个不同的序列化方式得到的结果,结合Bean中的属性的注解可以明显的看出,Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();这种方式,被@Expose注解的字段将被转成JSON,其他字段将被忽略。而Gson gson = new Gson()的GSON转换方式则不会理会@Expose注解。
以上,我们认识了Gson的序列化操作,接下来我们看看Gosn是如何反序列化的。
package com.gson.dalin.annotation;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.gson.dalin.MyEntity;
/**
* testGsion:自定义annotation,可以用来判断是不是被赋值(必填项检查)
* Date:2015/05/27
* @author dalin
*
*/
public class Main {
/**
* @param args
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) throws Exception {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
MyEntity entity = new MyEntity();
entity.setId(123456L);
entity.setUserName("Test User");
entity.setAddress("金茂中路");
entity.setDate(new Date());
String json = gson.toJson(entity);
System.out.println("Using Expose:" + json);
// 从json反射到Object
String className = "com.gson.dalin.MyEntity";
Class classDef = Class.forName(className);
Object logObj = gson.fromJson(json, classDef);
/**
* 注解解释器(用来解析通过注解给变量所赋的值)
*/
Field[] fields = classDef.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
boolean isPresent = fields[i].isAnnotationPresent(FieldComment.class);
if (isPresent) {
// 取注解中的文字说明
FieldComment comment = fields[i].getAnnotation(FieldComment.class);
String fieldComment = comment.value();
// 取对象中字段的值
fields[i].setAccessible(true); // 设置为可访问private字段
Object fieldValue = fields[i].get(logObj);
String content = String.format("%s:%s", fieldComment, fieldValue);
System.out.println(content);
}
}
}
}
结果:
Using Expose:{"id":123456,"userName":"Test User","address":"金茂中路","date":"May 27, 2015 10:04:01 PM"}
用户ID:123456
用户名:Test User
另:如果序列化/反序列化带有泛型的集合时使用如下代码来获取序列化/反序列化时的Class:
java.lang.reflect.Type type = new com.google.gson.reflect.TypeToken<Map<String, MyEntity>>(){}.getType();
最后,给大家一个彩果:以上反序列化代码同时可以完成标注属性必填项检查(依据对Bean属性中是否标记annotation来判断来属性是否有值。)