Gson学习笔记

谷歌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来判断来属性是否有值。)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值