最全Gson使用
作者:Liberuman
Gson是Google开源的一个JSON库,被广泛应用在Android开发中。
说明:以下所有的用法都基于Account类!
public class Account { private String uid; private String userName; private String password; private String telNumber; public Account(String uid, String userName, String telNumber) { this.uid = uid; this.userName = userName; this.telNumber = telNumber; } @Override public String toString() { return "Account [uid=" + uid + ", userName=" + userName + ", password=" + password + ", telNumber=" + telNumber + "]"; } }
基础用法
集成Gson
dependencies { implementation 'com.google.code.gson:gson:2.8.5' }
创建Gson对象
Gson提供了两种创建对象的方式:
直接使用Gson构造方法创建;
Gson gson = new Gson();
使用GsonBuilder创建;
Gson gson = new GsonBuilder().create();
相比直接使用构造方法,GsonBuilder创建的方式更灵活,因为它支持对Gson的配置。
将对象转换为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提供了多种过滤方式,这里说说两种最常用的。
通过修饰符过滤
Gson gson = new GsonBuilder() // 过滤transient或static修饰的字段, .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC).create();
自定义过滤规则
通过实现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闪退。
开发中经常遇到的类型兼容问题汇总:
- 使用Number类型接收,返回了String或空值(Gson已处理此类问题);
- 使用数组接收,返回了对象类型;
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();
总结
到此这篇关于最全Gson使用的文章就介绍到这了,更多相关Gson使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!