LayneYao的博客

天道酬勤,运筹帷幄

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

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包下载

阅读更多

扫码向博主提问

去开通我的Chat快问

jsagacity

一个技术人
  • 擅长领域:
  • Android开发
  • 偏物联网方向
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明作者和出处。 https://blog.csdn.net/Jsagacity/article/details/78123410
文章标签: json gson
个人分类: Android
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭