Gson

21 篇文章 0 订阅
2 篇文章 0 订阅

这是我使用的Gson包版本

下面是官方介绍

Gson

  • Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of.

  • There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes; something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals.

Goals

  • Provide simple toJson() and fromJson() methods to convert Java objects to JSON and vice-versa
  • Allow pre-existing unmodifiable objects to be converted to and from JSON
  • Extensive support of Java Generics
  • Allow custom representations for objects
  • Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types)
Gson
- Gson是一个Java库,可用于将Java对象转换为其JSON表示形式。它还可以用于将JSON字符串转换为等效的Java对象。Gson可以处理任意Java对象,包括您没有源代码的现有对象。
- 有一些开源项目可以将Java对象转换为JSON。但是,大多数方法都要求您在类中放置Java批注。如果您无法访问源代码,则无法执行某些操作。大多数还不完全支持Java泛型的使用。Gson认为这两个都是非常重要的设计目标。

目标
- 提供简单的toJson()fromJson()方法,将Java对象到JSON,反之亦然
- 允许将现有的不可修改对象与JSON相互转换
- Java泛型的广泛支持
- 允许对象的自定义表示
- 支持任意复杂的对象(具有深层继承层次结构和泛型类型的广泛使用)
<dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.8.6</version>
</dependency>

主要类

在这里插入图片描述

ClassDescription
FieldAttributesA data object that stores attributes of a field.
GsonThis is the main class for using Gson.
GsonBuilderUse this builder to construct a Gson instance when you need to set configuration options other than the default.
JsonArrayA class representing an array type in Json.
JsonElementA class representing an element of Json.
JsonNullA class representing a Json null value.
JsonObjectA class representing an object type in Json.
JsonParserA parser to parse Json into a parse tree of JsonElements
JsonPrimitiveA class representing a Json primitive value.
JsonStreamParserA streaming parser that allows reading of multiple JsonElements from the specified reader asynchronously.
TypeAdapterConverts Java objects to and from JSON.

使用

创建Gson对象

Gson提供了两种创建对象的方式:

  • 直接使用Gson构造方法创建;
Gson gson = new Gson();
  • 使用GsonBuilder创建(推荐GsonBuilder创建的方式更灵活,因为它支持对Gson的配置);
Gson gson = new GsonBuilder().create();
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PROTECTED).create();//忽略PROTECTED

在这里插入图片描述

方法

在这里插入图片描述

将对象转换为JSON
Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));
	
ArrayList<Account> accountList = new ArrayList<Account>();
accountList.add(account);
System.out.println(gson.toJson(accountList));
复制代码

结果:

{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}
[{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}]
复制代码
将JSON转换为对象

由于Java中的泛型存在类型擦除的问题,所以使用泛型接收JSON解析结果的时候有点特殊。

普通对象解析
String json = "{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}";
Account receiveAccount = gson.fromJson(json, Account.class);
System.out.println(receiveAccount.toString());
复制代码

结果:

Account [uid=00001, userName=Freeman, password=null, telNumber=13000000000]
复制代码
泛型对象解析
String listJson = "[{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}]";
List receiveAccountList = gson.fromJson(listJson, new TypeToken<List<Account>>(){}.getType());
System.out.println("receiveAccountList size = " + receiveAccountList.size());
复制代码

结果:

receiveAccountList size = 1
复制代码
字段复用

在开发中有时会对Bean对象进行复用,但可能有几个字段的命名和当前的对象不一致,这样在解析JSON的时候就不能正确赋值。Gson提供了字段复用功能——@SerializedName,可用一个字段接收不同的JSON字段。

// json字符串中手机号的字段为phone或telNumber时都可正确解析
@SerializedName("phone")
private String telNumber;

// json字符串中用户名的字段为userName、user_name、uname或u_name时都可正确解析
@SerializedName(value = "userName", alternate = {"user_name", "uname", "u_name"})
private String userName;
复制代码

Gson配置

除了以上用法,Gson还提供了丰富的配置选项,包括:空值过滤,字段命名规则,自定义解析器,自定义序列化/反序列化等。

空值问题

Gson默认情况下会过滤空值字段,但有时在提交数据给后台时,即便字段为空,也需要传给后台,此时可通过GsonBuilder进行配置。

gson = new GsonBuilder().serializeNulls().create();
Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));

结果:

{"uid":"00001","userName":"Freeman","password":null,"phone":"13000000000"}

从结果可以看出,password字段被输出了,而前面直接创建Gson转换的时候没有输出password字段。

字段命名转换规则

因为不同的语言使用不同的命名规则,这会出现为了正确解析JSON字符串,而使用不符合命名规则的字段名。如PHP使用小写字母下划线分割的命名方式,而Java使用骆驼命名的方式,这样Android程序在接收JSON字符串的时候就需要使用小写字母下划线分割的命名方式,然而这并不符合Java的命名规范。为了解决这个问题,Gson提供了丰富的字段命名规则。

// 默认的字段转换规则,字段名不变
FieldNamingPolicy.IDENTITY()

// 将json中的字段名转换为首字母大写的格式
FieldNamingPolicy.UPPER_CAMEL_CASE()
如:"user_name" -> "UserName"

// 将json中的字段名转换为首字母大写,单词之间以空格分割的格式
FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES()
如:"user_name" -> "User Name"

// 将json中的字段名转换为小写字母,单词之间以下划线分割的格式
FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES()
如:"UserName" -> "user_name"

// 将json中的字段名转换为小写字母,单词之间以分隔线分割的格式
FieldNamingPolicy.LOWER_CASE_WITH_DASHES()
如:"UserName" -> "user-name"

所以对于服务器是PHP的情况,Android端可使用FieldNamingPolicy.UPPER_CAMEL_CASE转换规则。

Gson gson = new GsonBuilder()
	.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
	.create();

当然,如果上面几种命名转换规则不满足需求,也可自定义命名转换规则,只需要实现FieldNamingStrategy接口,并完善translateName方法即可。需要注意的是,命名转换规则会同时被应用于序列化和反发序列化,所以在将对象转换为JSON(序列化)传给后台时需要注意。

字段过滤

默认情况下,Gson将对象转换为JSON时,会将所有非null字段进行转换,但有时为了业务需求,通常会添加一些状态字段,如表示item选中状态的isSelected,这些字段通常不希望被转换。Gson提供了多种过滤方式,这里说说两种最常用的。

  1. 通过修饰符过滤
   Gson gson = new GsonBuilder() // 过滤transient或static修饰的字段, 
   .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC) .create();
  1. 自定义过滤规则

通过实现setExclusionStrategies接口来定义过滤规则:

ExclusionStrategy strategy = new ExclusionStrategy() {

	@Override
	public boolean shouldSkipClass(Class<?> arg0) {
		// 过滤指定的类
		return false;
	}

	@Override
	public boolean shouldSkipField(FieldAttributes arg0) {
		// 过滤指定的字段
		return false;
	}
	
};

Gson gson = new GsonBuilder()
	// 过滤规则同时适用于序列化/反序列化
	.setExclusionStrategies(strategy)
	// 过滤规则只适用于序列化
	.addSerializationExclusionStrategy(strategy)
	// 过滤规则只适用于反序列化
	.addDeserializationExclusionStrategy(strategy)
	.create();
字段容错性

字段容错性主要表现在字段的类型不匹配,比如接收的字段是整型,返回的却是字符串或者null, 这种情况情况直接使用String接收整型倒可以解决,但对于接收类型是数组,返回的确是对象的情况,却不能直接使用类型兼容来处理。

虽然这些情况都是因为后台数据格式的问题,但对用户最直观的感受是APP闪退了。所以我们需要对JSON的解析过程做一定的兼容处理,以防出现异常数据时导致APP闪退。

开发中经常遇到的类型兼容问题汇总:

  1. 使用Number类型接收,返回了String或空值(Gson已处理此类问题);
  2. 使用数组接收,返回了对象类型;

Gson提供了多种序列化/反序列化方式,由于这里我们只做JSON解析(即反序列化)的兼容处理,所以直接实现JsonDeserializer接口即可。

// 为数组类型自定义反序列化适配器
JsonDeserializer<List<?>> listDeserial = new JsonDeserializer<List<?>>() {
	@Override
	public List<?> deserialize(JsonElement arg0, java.lang.reflect.Type arg1,
			JsonDeserializationContext arg2) throws JsonParseException {
		if (arg0.isJsonArray()) {
			JsonArray jsonArray = arg0.getAsJsonArray();
			if (jsonArray.size() == 0) {
				return Collections.EMPTY_LIST;
			}
			List<?> resultList = new ArrayList<>();
			for (JsonElement element : jsonArray) {
				resultList.add(arg2.deserialize(element, arg1));
			}
			return resultList;
		} else {
			return Collections.EMPTY_LIST;
		}
	}
};

Gson gson = new GsonBuilder()
    // 注册自定义的反序列化适配器
	.registerTypeHierarchyAdapter(List.class, listDeserial)
	.create();
Gson常用配置总结
gson = new GsonBuilder()
    // 不过滤空值
    .serializeNulls()
    // 设置字段命名转换规则
    .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
    // 设置字段序列化/反序列化过滤规则
    .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC)
    // 自定义类型解析器,提高Gson容错性
    .registerTypeHierarchyAdapter(List.class, listDeserial)
    .create();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值