Android框架---Google官方Gson解析(上)

原创 2017年09月28日 14:41:04

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。

GitHub中的源码地址:https://github.com/google/gson

AS在项目的app目录下的buile.gradle添加gson依赖:(如果需要jar包,文末可以下载)



Gson的实例化方式:

Gson gson = new Gson();
//可以通过GsonBuilder配置多种选项
gson = new GsonBuilder()
        .setLenient()// json宽松
        .enableComplexMapKeySerialization()//支持Map的key为复杂对象的形式
        .serializeNulls() //智能null
        .setPrettyPrinting()// 调教格式
        .disableHtmlEscaping() //默认是GSON把HTML 转义的
        .create();

接下来介绍Gson的集中基本用法:

1、对象和json字符串的相互转换(先准备一个Person类)

public class Person {
	private int per_id;
	private String name;
	private String sex;
	private int age;

	public Person(int per_id, String name, String sex, int age) {
		this.per_id = per_id;
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	
	//get、set和toString方法...
}

测试代码:

/**
 * Created by Layne_Yao on 2017-9-28 上午10:46:43.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class GsonTest {

	public static void main(String[] args) {
		Gson gson = new Gson();
		// 可以通过GsonBuilder配置多种选项
		gson = new GsonBuilder()
				.setLenient()// json宽松
				.enableComplexMapKeySerialization()// 支持Map的key为复杂对象的形式
				.serializeNulls() // 智能null
				.setPrettyPrinting()// 调教格式
				.disableHtmlEscaping() // 默认是GSON把HTML 转义的
				.create();

		Person person = new Person(10, "layne", "man", 18);
		// 对象转换为json字符串
		String str = gson.toJson(person);
		System.out.println("对象转换为json字符串:" + str);

		// json字符串转化为对象
		Person person1 = gson.fromJson(str, Person.class);
		System.out.println("json字符串转化为对象:" + person1.toString());

	}

}

运行结果:



2、集合和json字符串之间的转换:

/**
 * Created by Layne_Yao on 2017-9-28 上午11:03:21.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class CollectionTest {
	public static void main(String[] args) {
		Gson gson = new Gson();

		// 1.1、List字符串集合转换为字符串
		ArrayList<String> str_list = new ArrayList<>();
		for (int i = 0; i < 5; i++) {
			str_list.add("这是字符串" + i);
		}
		String json_str = gson.toJson(str_list);
		System.out.println("这是list字符串集合转化为json:" + json_str);
		
		// 1.2、这是json集合转化为list字符集合
		Type type = new TypeToken<ArrayList<String>>() {
		}.getType();
		ArrayList<String> sList = gson.fromJson(json_str, type);
		System.out.println("这是json集合转化为list字符集合:" + sList);
		System.out.println("==========================================");
		
		
		// 2.1、List对象集合转换为字符串
		List<Person> list = new ArrayList<>();
		for (int i = 0; i < 2; i++) {
			Person person = new Person(i, "layne", "man", 18);
			list.add(person);
		}
		String json_str1 = gson.toJson(list);
		System.out.println("这是list对象集合转化为json:" + json_str1);
		
		// 2.1、这是json转化为List对象集合
		Type type1 = new TypeToken<ArrayList<Person>>() {
		}.getType();
		ArrayList<String> sList1 = gson.fromJson(json_str1, type1);
		System.out.println("这是json转化为List对象集合:" + sList1);
		System.out.println("==========================================");
		
		
		//3.1、这是map集合转化为json
		Map<String, Object> map = new HashMap<>();
		map.put("per_id", 5);
		map.put("name", "layne");
		map.put("sex", "man");
		map.put("age", "18");
		
		String json_str2 = gson.toJson(map);
		System.out.println("这是map集合转化为json:" + json_str2);
		
		//3.2、从json字符串转化为map集合
		Type type2 = new TypeToken<Map<String, Object>>() {
		}.getType();
		Map<String, Object> map1 = gson.fromJson(json_str2, type2);
		System.out.println("这是json转化为map集合:" + map1);
		
	}
}

运行结果:


接下来介绍抽象基类JsonElement的继承体系类:

JSONObject、JSONArray和Android自带的差不多,参见上篇Android网络传输数据json解析的基本认识

JsonNull:实际上就是null的字符串字段

JsonPrimitive:这个其实挺有意思的,我们知道如果json转换成字符串会包含引号的转义,但是通过JsonPrimative我们可以获得为转义的字符串

/**
 * Created by Layne_Yao on 2017-9-28 下午1:52:31.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class JsonTest {

	public static void main(String[] args) {
		// JsonNull jsonNull = new JsonNull();// 构造方法过时,推荐INSTANCE

		JsonNull jsonNull = JsonNull.INSTANCE;
		System.out.println("JsonNull:" + jsonNull);

		
		Gson gson = new Gson();
		Person person = new Person(1, "layne", "man", 18);
		String json_str = gson.toJson(person);
		System.out.println("json字符串:" + json_str);

		JsonPrimitive jsonPrimitive = new JsonPrimitive(json_str);
		System.out.println("JsonPrimitive字符串:" + jsonPrimitive);// 多了转义字符,以及头尾的双引号:"{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"age\":18}"
		System.out.println("JsonPrimitive字符串:" + jsonPrimitive.getAsString());	
	}
}

运行结果:



Gson库中的注解:有五种注解


首先着重的先说明重命名注解:SerializedName

注解的作用:转换key关键字,json转换成对象是,json字段的key默认必须和声明类的字段名称一样。但是如果服务器返回的数据中key是关键字,这该怎么办?例如key是case、switch等,我们在声明类的时候是不能用这些字段的。或许你会让服务端那边改动,那服务端可能要改动非常的大,但是实际情况是不太愿意去改的。而这时候重命名注解就派上用场了。
还有就是如果服务端返回的json的key太冗余、或是不直观,这是就可以简化一下,代码看起来比较的优雅。

替换关键字的key:

/**
 * Created by Layne_Yao on 2017-9-28 下午4:08:23.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class AnnotationTest {
	public class Person {
		private int per_id;
		private String name;
		private String sex;
		@SerializedName("case")
		private int case_num;

		public Person(int per_id, String name, String sex, int case_num) {
			super();
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.case_num = case_num;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", case_num=" + case_num + "]";
		}

	}

	public static void main(String[] args) {
		Gson gson = new Gson();
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"case\":18}";
		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("服务端发送的情况:"+json_str);
		System.out.println("移动端转换的情况:"+person);
	}

}

运行结果:



替换冗余、难看的key:

/**
 * Created by Layne_Yao on 2017-9-28 下午4:16:44.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class AnnotationTest1 {
	public class Person {
		private int per_id;
		private String name;
		private String sex;
		@SerializedName("home_light_state")
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			super();
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person [per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}
	}

	public static void main(String[] args) {
		Gson gson = new Gson();
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"home_light_state\":true}";
		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("服务端发送的情况:"+json_str);
		System.out.println("移动端转换的情况:"+person);
	}

}

运行结果:



注解作用2:结合alternate 提供多种备用字段key来解析,@SerializedName(value = "state", alternate = { "plus", "all" })
如果json中有plus就会解析成state,如果有all也会解析成state,当然state依旧不变的。
注意1:value中的值不能出现在alternate中;
注意2:alternate的备选字段会后面的替换前面的。

实例代码:

/**
 * Created by Layne_Yao on 2017-9-28 下午5:05:44.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class AnnotationTest2 {
	public class Person {
		private int per_id;
		private String name;
		private String sex;
		@SerializedName(value = "state", alternate = { "plus", "all" })
		private String state;

		public Person(int per_id, String name, String sex, String state) {
			super();
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person [per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}
	}

	public static void main(String[] args) {
		Gson gson = new Gson();
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"all\":\"广东广州\"}";
		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("服务端发送:"+json_str);
		System.out.println("转换成:" + person);
		System.out.println("==========================");

		String json_str1 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"plus\":\"广东广州\"}";
		Person person1 = gson.fromJson(json_str1, Person.class);
		System.out.println("服务端发送:"+json_str1);
		System.out.println("转换成:" + person1);
		System.out.println("==========================");
		
		//all在state之后,所以all会解析成state,值则是all的原先的值
		String json_str2 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":\"state广东广州\",\"all\":\"all广东广州\"}";
		Person person2 = gson.fromJson(json_str2, Person.class);
		System.out.println("服务端发送:"+json_str2);
		System.out.println("转换成:" + person2);
		System.out.println("==========================");
		
		//state在最后,不用解析,解析后的值也是state原先的
		String json_str3 = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"plus\":\"plus广东广州\",\"state\":\"all广东广州\"}";
		Person person3 = gson.fromJson(json_str3, Person.class);
		System.out.println("服务端发送:"+json_str3);
		System.out.println("转换成:" + person3);
		System.out.println("==========================");
	}

}

运行结果:


过滤注解:Expose

源码:默认既可序列化又可反序列化

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
  
  public boolean serialize() default true;

  public boolean deserialize() default true;
}

可以排除不需要序列化的字段,需要配合GsonBuilder使用

Gson gson = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation()
                .create();

不添加@Expose注解的字段将不会解析,分为以下几种情况:

1、不添加@Expose注解等同于@Expose(deserialize = false,serialize = false) 不做任何解析
2、@Expose(deserialize = true,serialize = false) 只解析用用,也就是反序列化可以,序列化不可以
3、@Expose(deserialize = false,serialize = true) 序列化可以,反序列化不行
4、@Expose(deserialize = true,serialize = true) 既可以序列化,也可以反序列化

实例代码:不添加@Expose注解等同于@Expose(deserialize = false,serialize = false) 不做任何解析

/**
 * Created by Layne_Yao on 2017-9-29 上午9:29:08.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class ExposeTest {
	public static class Person {
		private int per_id;
		private String name;
		private String sex;
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}

	}

	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化:"+json_str1);
	}
}

运行结果:



@Expose(deserialize = true,serialize = false) 只解析用用,也就是反序列化可以,序列化不可以

/**
 * Created by Layne_Yao on 2017-9-29 上午9:59:04.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class ExposeTest3 {
	public static class Person {
		@Expose(deserialize = true,serialize = false)
		private int per_id;
		@Expose(deserialize = true,serialize = false)
		private String name;
		@Expose(deserialize = true,serialize = false)
		private String sex;
		@Expose(deserialize = true,serialize = false)
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}

	}
	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化:"+json_str1);
	}
}

运行结果:



@Expose(deserialize = false,serialize = true) 序列化可以,反序列化不行

/**
 * Created by Layne_Yao on 2017-9-29 上午9:56:57.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class ExposeTest2 {
	public static class Person {
		@Expose(deserialize = false,serialize = true)
		private int per_id;
		@Expose(deserialize = false,serialize = true)
		private String name;
		@Expose(deserialize = false,serialize = true)
		private String sex;
		@Expose(deserialize = false,serialize = true)
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}

	}
	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化:"+json_str1);
	}
}

运行结果:



@Expose(deserialize = true,serialize = true) 既可以序列化,也可以反序列化

/**
 * Created by Layne_Yao on 2017-9-29 上午9:53:38.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class ExposeTest1 {
	public static class Person {
		@Expose //等同于 @Expose(deserialize = true,serialize = true)
		private int per_id;
		@Expose
		private String name;
		@Expose
		private String sex;
		@Expose
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}

	}

	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化:"+json_str1);

	}

}

运行结果:



版本控制注解:Since、Util

Since注解:Gson实例配置GsonBuilder.setVersion(n)使用,当n>=v时,才会序列化解析

实例代码:

/**
 * Created by Layne_Yao on 2017-9-29 上午10:00:37.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class SinceTest {
	public static class Person {
		 @Since(2)
		private int per_id;
		 @Since(2)
		private String name;
		 @Since(2)
		private String sex;
		 @Since(2)
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}

	}
	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().setVersion(1)//版本为1
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化v=1:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化v=1:"+json_str1);
		System.out.println("=================================");
		
		Gson gson1 = new GsonBuilder().setVersion(2)//版本为2
				.create();
		Person person2 = gson1.fromJson(json_str, Person.class);
		System.out.println("反序列化v=2:" + person2);

		Person person3 = new Person(2, "layne", "man", true);
		String json_str2 = gson1.toJson(person3);
		System.out.println("序列化v=2:"+json_str2);
		System.out.println("=================================");
		
		Gson gson2 = new GsonBuilder().setVersion(3)//版本为3
				.create();
		Person person4 = gson2.fromJson(json_str, Person.class);
		System.out.println("反序列化v=3:" + person4);

		Person person5 = new Person(2, "layne", "man", true);
		String json_str3 = gson2.toJson(person5);
		System.out.println("序列化v=3:"+json_str3);
	}

}

运行结果:



Util注解:Gson实例配置GsonBuilder.setVersion(n)使用,当n<v时,才会序列化解析

实例代码:

/**
 * Created by Layne_Yao on 2017-9-29 上午10:17:54.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public class UtilTest {
	public static class Person {
		@Until(2)
		private int per_id;
		@Until(2)
		private String name;
		@Until(2)
		private String sex;
		@Until(2)
		private boolean state;

		public Person(int per_id, String name, String sex, boolean state) {
			this.per_id = per_id;
			this.name = name;
			this.sex = sex;
			this.state = state;
		}

		@Override
		public String toString() {
			return "Person-->[per_id=" + per_id + ", name=" + name + ", sex="
					+ sex + ", state=" + state + "]";
		}
	}

	public static void main(String[] args) {
		String json_str = "{\"per_id\":1,\"name\":\"layne\",\"sex\":\"man\",\"state\":true}";
		Gson gson = new GsonBuilder().setVersion(1)// 版本为1
				.create();

		Person person = gson.fromJson(json_str, Person.class);
		System.out.println("反序列化v=1:" + person);

		Person person1 = new Person(2, "layne", "man", true);
		String json_str1 = gson.toJson(person1);
		System.out.println("序列化v=1:" + json_str1);
		System.out.println("=================================");

		Gson gson1 = new GsonBuilder().setVersion(2)// 版本为2
				.create();
		Person person2 = gson1.fromJson(json_str, Person.class);
		System.out.println("反序列化v=2:" + person2);

		Person person3 = new Person(2, "layne", "man", true);
		String json_str2 = gson1.toJson(person3);
		System.out.println("序列化v=2:" + json_str2);
		System.out.println("=================================");

		Gson gson2 = new GsonBuilder().setVersion(3)// 版本为3
				.create();
		Person person4 = gson2.fromJson(json_str, Person.class);
		System.out.println("反序列化v=3:" + person4);

		Person person5 = new Person(2, "layne", "man", true);
		String json_str3 = gson2.toJson(person5);
		System.out.println("序列化v=3:" + json_str3);

	}

}

运行结果:


Gson2.7jar包下载

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

google官方架构MVP解析与实战-(从零开始搭建android框架系列(3))

最近更新2016.5.10(已经添加整个项目目录。更新新闻资讯) 本篇文章项目github地址:MVPCommon 本文章原地址:简书博客1 前言当然对于MVP的解说也是使用也是层出不穷,我也网络...

google官方架构MVP解析与实战【从零开始搭建android框架系列(3)】

google官方架构MVP解析与实战【从零开始搭建android框架系列(3)】 字数2387 阅读14518 评论20 喜欢116 更多及时技术资讯,欢迎关注我的微博 :Anth...

android JSON解析:官方&GSON方式

同样在apache/hotdoc目录下创建get_data.json文件,内容如下:[{"id":"5","version":"5.5","name":"Boom Beach"}, {"id":"6"...

Google官方MVP+Dagger2架构详解【从零开始搭建android框架系列(6)】

Google官方MVP+Dagger2架构详解【从零开始搭建android框架系列(6)】 字数6894 阅读13459 评论37 喜欢125 更多及时技术资讯,欢迎关注我的微博 ...

Android 单元测试之Espresso - Google官方UI测试框架

Android 单元测试之Espresso - Google官方UI测试框架Espresso是Google官方推出的Instrumentation UI测试框架,在API支持方面有着天然的优势,在推出...
  • EthanCo
  • EthanCo
  • 2016年08月29日 09:02
  • 1345

图解Google官方示例的各种android框架

Goolge官方的Android框架源码见:GitHub工程; 毋庸置疑,官方给出的框架示例应该是最标准也最具有普适性的。本文根据工程中的示例,画出了各个框架的架构图,以方便快速学习和了解。 1。...
  • chwnpp2
  • chwnpp2
  • 2017年04月05日 18:04
  • 514

Android网络之数据解析----使用Google Gson解析Json数据

一、Json数据的介绍 ...

Google官方网络框架-Volley的使用解析Json以及加载网络图片方法

Goole官方网络框架-Volley的使用解析Json以及加载网络图片方法 Volley是什么? Google I/O 大会上,Google 推出 Volley的一个网络框架 Volley适合什么...

Google Gson官方教程

Google gson
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android框架---Google官方Gson解析(上)
举报原因:
原因补充:

(最多只允许输入30个字)