@html
Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。java
Gson官网:gson Gson源码地址:google/gsongit
使用Maven导入依赖:github
<dependency>
<groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> 复制代码
Gradle导入依赖:web
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
复制代码
使用Gson的第一步是建立一个Gson对象,建立爱你Gson对象有两种方式:编程
示例以下:json
Gson gson = new Gson();
复制代码
示例以下:数组
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create(); 复制代码
下面会用到这个实体类:网络
public class Employee {
private int id; private String firstName; private String lastName; private String email; //省略getter/setter,构造方法,toSting方法 } 复制代码
在Gson中的序列化即将Java对象转换为其JSON表示形式。 为了进行序列化,首先须要一个Gson对象,该对象能够处理转换。 接下来,须要调用函数toJson()方法并传入Employee对象。maven
Employee emp = new Employee(1001, "Lokesh", "Gupta", "howtodoinjava@gmail.com");
Gson gson = new Gson(); String jsonString = gson.toJson(emp); System.out.println(jsonString); 复制代码
运行结果:
在Gson进行反序列指的是将JSON字符串转换为Java对象。 为了进行反序列化,咱们须要使用Gson对象调用fromJson()函数,并在解析完成后传递两个参数,即JSON字符串和所需的Java类型。
String jsonString = "{'id':1001, 'firstName':'Lokesh', 'lastName':'Gupta', 'email':'howtodoinjava@gmail.com'}";
Gson gson = new Gson(); Employee empObject = gson.fromJson(jsonString, Employee.class); System.out.println(empObject); 复制代码
运行结果:
默认状况下,Gson以紧凑格式打印JSON,即字段名称及其值,对象字段以及JSON输出中数组内的对象等之间将没有空格。
{"id":1,"firstName":"Lokesh","lastName":"Gupta", "emailId":"howtogoinjava@gmail.com"}
复制代码
可是,这种紧凑的JSON可能很难阅读。所以,GSON提供了一个漂亮的打印选项,能够在其中打印JSON,以便于更加方便阅读。
Gson gson = new GsonBuilder()
.setPrettyPrinting() .create(); Employee employeeObj = new Employee(1, "Lokesh", "Gupta", "howtogoinjava@gmail.com"); System.out.println(gson.toJson(employeeObj)); 复制代码
运行结果:
users.json:
[
{ "name": "Alex", "id": 1 }, { "name": "Brian", "id": 2 }, { "name": "Charles", "id": 3 } ] 复制代码
User.java:
public class User { private long id; private String name; 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; } @Override public String toString() { return "User [id=" + id + ", name=" + name + "]"; } } 复制代码
将json数组反序列化为Java对象数组:
String userJson = "[{'name': 'Alex','id': 1}, "
+ "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]"; Gson gson = new Gson(); User[] userArray = gson.fromJson(userJson, User[].class); for(User user : userArray) { System.out.println(user); } 复制代码
运行结果:
将json数组反序列化为根–到Java对象列表:
String userJson = "[{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]";
Gson gson = new Gson(); java.lang.reflect.Type userListType = new TypeToken<ArrayList<User>>() { }.getType(); ArrayList<User> userArray = gson.fromJson(userJson, userListType); for (User user : userArray) { System.out.println(user); } 复制代码
运行结果:
若是Json数组是非根对象,则Gson能够将JSON数组解析为成员变量。咱们能够按一般的方式使用fromJson()方法,将json数组解析为所需的Java数组或列表。
department.json:
{
"id" : 1, "name" : "HR", "users" : [ { "name": "Alex", "id": 1 }, { "name": "Brian", "id": 2 }, { "name": "Charles", "id": 3 } ] 复制代码
Department.java:
public class Department {
private long id; private String name; private User[] users; //省略getter/setter、构造方法、toString方法 } 复制代码
JsonArrayToMemberArray.java:
String departmentJson = "{'id' : 1, "
+ "'name': 'HR'," + "'users' : [" + "{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]}"; Gson gson = new Gson(); Department department = gson.fromJson(departmentJson, Department.class); System.out.println(department); 复制代码
运行结果:
将json数组反序列化为List类型成员变量。
Department2.java:
public class Department2 {
private long id; private String name; private List<User> users; //省略getter/setter、构造方法、toString方法 } 复制代码
转换:
String departmentJson = "{'id' : 1, "
+ "'name': 'HR'," + "'users' : [" + "{'name': 'Alex','id': 1}, " + "{'name': 'Brian','id':2}, " + "{'name': 'Charles','id': 3}]}"; Gson gson = new Gson(); Department2 department = gson.fromJson(departmentJson, Department2.class); System.out.println(department); 复制代码
运行结果:
使用Gson.toJson()方法将HashSet序列化为JSON:
Set<String> userSet = new HashSet<String>();
userSet.add("Alex"); userSet.add("Brian"); userSet.add("Charles"); Gson gson = new Gson(); String jsonString= gson.toJson(userSet); System.out.println(jsonString); 复制代码
运行结果:
使用Gson.fromJson()方法和TypeToken将JSON反序列化为HashSet:
String jsonString = "['Alex','Brian','Charles','Alex']";
Gson gson = new Gson(); java.lang.reflect.Type setType = new TypeToken<HashSet<String>>(){}.getType(); Set<String> userSet = gson.fromJson(jsonString, setType); System.out.println(userSet); 复制代码
运行结果:
Gson中实现的默认行为是忽略空对象字段。
例如,若是在Employee对象中未指定电子邮件(即email为null),则电子邮件将不会被序列化JSON输出。Gson会忽略null字段,由于此行为容许使用更紧凑的JSON输出格式。
要配置Gson实例以输出null,咱们必须使用GsonBuilder对象的serializeNulls()。
Gson gson = new GsonBuilder()
.serializeNulls() .create(); 复制代码
应用程序随着时间变化,模型类也随之变化。有时候更新/删除字段可能会被打断。
全部这些更改均可以使用@Since注释进行标记,以跟踪模型类,在这些系统使用反序列化JSON数据进行交换时,与其余系统的应用程序交互不会中断。
在Gson中,可使用@Since注释维护同一对象的多个版本。能够在类,字段以及未来的方法中使用此注释。它采用单个参数– ignoreVersionsAfter。
当咱们为Gson实例配置版本号“ M.N”时,全部标记有版本大于M.N的类字段都将被忽略。例如,若是咱们将Gson配置为版本号“ 1.2”,则全部版本号更高的字段(例如1.三、1.4…)都将被忽略。
@Since(1.2)
private String email; 复制代码
在Employee类下面,咱们对三个字段进行了版本控制,即firstName,lastName和email。
public class Employee { private Integer id; @Since(1.0) private String firstName; @Since(1.1) private String lastName; @Since(1.2) private String email; } 复制代码
要建立使用过@Since注解的Gson实例,须要使用GsonBuilder.setVersion()方法:
Gson gson = new GsonBuilder()
.setVersion(1.1) .create(); 复制代码
让序列号以上的Employee对象序列化。
Employee employeeObj = new Employee(1, "Lokesh", "Gupta", "howtogoinjava@gmail.com");
Gson gson = new GsonBuilder() .setVersion(1.1) .setPrettyPrinting() .create(); System.out.println(gson.toJson(employeeObj)); 复制代码
输出:
{
"id": 1, "firstName": "Lokesh", "lastName": "Gupta" } 复制代码
咱们将JSON字符串反序列化为版本号为Employee的对象。
String json = "{'id': 1001, "
+ "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; Gson gson = new GsonBuilder() .setVersion(1.1) .setPrettyPrinting() .create(); Employee employeeObj = gson.fromJson(json, Employee.class); System.out.println(employeeObj); 复制代码
输出:
Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=null]
复制代码
在此Gson @SerializedName示例中,演示在序列化和反序列化过程当中更改json和java对象之间的字段名称。
默认状况下,咱们假设Java模型类和JSON将具备彻底相同的字段名称。
但有时状况并不是如此,某些名称有所不一样。如今咱们必须将json中的someName映射到Java类中的someOtherName。这是@SerializedName注解用到的地方。
@SerializedName注解指示带注解的成员变量应使用提供的名称值做为其字段名称序列化为JSON。此注解将覆盖可能一直在使用GsonBuilder类的任何FieldNamingPolicy,包括默认的字段命名策略。
请注意,在此注解中指定的值必须是有效的JSON字段名称。
注解包含属性
让咱们以只有四个字段的Employee类为例。咱们要建立一个JSON,其中“ email”被写为字段名“ emailId”:
public class Employee { private Integer id; private String firstName; private String lastName; @SerializedName(value = "emailId", alternate = "emailAddress") private String email; } 复制代码
让咱们序列化一个Employee实例并查看JSON输出:
Employee emp = new Employee(1001, "Lokesh", "Gupta", "howtodoinjava@gmail.com");
Gson gson = new GsonBuilder().setPrettyPrinting().create(); System.out.println(gson.toJson(emp)); 复制代码
输出:
{
"id": 1001, "firstName": "Lokesh", "lastName": "Gupta", "emailId": "howtodoinjava@gmail.com" } 复制代码
在将JSON反序列化为Java类的过程当中映射不一样的字段名称:
Json:
{
"id": 1001, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "emailAddress": "admin@gmail.com" } 复制代码
Main.java:
String json = "{'id': 1001,"
+ "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'," + "'emailAddress': 'admin@gmail.com'}"; Gson gson = new GsonBuilder().setPrettyPrinting().create(); Employee emp = gson.fromJson(json, Employee.class); System.out.println(emp); 复制代码
输出:
Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=admin@gmail.com]
复制代码
Gson容许咱们从Java类中排除或忽略不但愿包含在序列化和反序列化中的字段。
Gson支持许多内置机制,用于排除顶级类,字段和字段类型。
GSON @Expose注解(com.google.gson.annotations.Expose)可用于标记对象序列化或反序列化时是否公开(包括活不包括)的字段。
@Expose注释在要显式指定应进行序列化或反序列化的全部字段的编程方式中颇有用。
@Expose是可选的,并提供两个配置参数:
@Expose(serialize = false)
private String lastName; @Expose (serialize = false, deserialize = false) private String emailAddress; 复制代码
若是咱们使用 new Gson() 建立Gson并执行toJson() 和 fromJson() 方法,则@Expose将不会对序列化和反序列化产生任何影响。要使用此批注,咱们必须使用GsonBuilder类及其excludeFieldsWithoutExposeAnnotation()方法建立Gson实例。
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() .create(); 复制代码
默认状况下,若是咱们仅将字段标记为瞬时态,则Gson会将字段从序列化和反序列化中排除。
请记住,它没法阻止单向转换。它同时阻止了二者。
transient 具备与@Expose相同的效果(serialize = false,deserialize = false)。
@Expose(serialize = false)
private String lastName; private transient String emailAddress; 复制代码
经过使用GsonBuilder的excludeFieldsWithModifiers()方法,咱们能够排除具备某些公共修饰符的字段。
例如,咱们要排除一个类的全部静态成员,咱们能够这样建立Gson对象:
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC) .create(); 复制代码
咱们可使用任意数量的Modifier常量来“ excludeFieldsWithModifiers”方法。例如:
Gson gson = new GsonBuilder()
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE) .create(); 复制代码
若是以上任何一种技术都不适合咱们,那么咱们能够建立本身的策略。
ExclusionStrategy用于肯定是否应将字段或顶级类做为JSON输出/输入的一部分进行序列化或反序列化。
例如,在ExclusionStrategy定义下面,将排除全部使用@Hidden注释注释的字段:
//public @interface Hidden {
// some implementation here //} // Excludes any field (or class) that is tagged with an "@Hidden" public class HiddenAnnotationExclusionStrategy implements ExclusionStrategy { public boolean shouldSkipClass(Class<?> clazz) { return clazz.getAnnotation(Hidden.class) != null; } public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(Hidden.class) != null; } } 复制代码
要使用此排除策略,在GsonBuilder对象中进行设置:
GsonBuilder builder = new GsonBuilder();
builder.setExclusionStrategies( new HiddenAnnotationExclusionStrategy() ); Gson gson = builder.create(); 复制代码
对于简单的用例,使用'Gson gson = new Gson();' 标准配置就足够了。 可是,若是打算自定义Gson的行为,则可使用GsonBuilder自定义的配置来建立新的Gson实例。
GsonBuilder类提供一个.create()方法,该方法返回一个Gson实例。
Gson gson = new GsonBuilder().create();
复制代码
默认状况下,Gson将建立紧凑的JSON字符串。这对于减小经过网络传输的数据量很是有用。
可是,这种紧凑的JSON对开发人员进行开发/调试应用程序时不友好。使用漂亮的打印来格式化JSON输出:
Gson gson = new GsonBuilder()
.setPrettyPrinting() .create(); 复制代码
FieldNamingPolicy枚举在序列化期间为JSON字段名称提供了几种标准命名约定。
它有助于Gson实例将Java字段名称正确转换为所需的JSON字段名称。
注意:如下任何命名约定均不会影响以@SerializedName注释的字段。咱们将验证使用User类的每一个策略生成的名称。
User.java:
public class User { private int id; private String first_Name; private String lastName; private String _email; } 复制代码
如何使用FieldNamingPolicy:
User user = new User(1, "Lokesh", "Gupta", "admin@howtodoinjava.com");
Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .setPrettyPrinting().create(); System.out.println(gson.toJson(user)); 复制代码
如下演示每种命名策略下转换的不一样的名称。
使用此命名策略字段名称不变。这个是默认的策略:
{
"id": 1, "first_Name": "Lokesh", "lastName": "Gupta", "_email": "admin@howtodoinjava.com" } 复制代码
Gson会将Java字段名称从其驼峰大小写形式修改成小写的字段名称,其中每一个单词都用破折号(-)分隔。
{
"id": 1, "first_-name": "Lokesh", "last-name": "Gupta", "_email": "admin@howtodoinjava.com" } 复制代码
Gson会将Java字段名称从其驼峰大小写形式修改成小写的字段名称,其中每一个单词都用点(.)分隔:
{
"id": 1, "first_.name": "Lokesh", "last.name": "Gupta", "_email": "admin@howtodoinjava.com" } 复制代码
Gson会将Java字段名称从其驼峰大小写形式修改成小写的字段名称,其中每一个单词都用下划线(_)分隔。
{
"id": 1, "first__name": "Lokesh", "last_name": "Gupta", "_email": "admin@howtodoinjava.com" } 复制代码
Gson将确保序列化为JSON格式的Java字段名称的第一个“字母”大写:
{
"Id": 1, "First_Name": "Lokesh", "LastName": "Gupta", "_Email": "admin@howtodoinjava.com" } 复制代码
Gson将确保在将Java字段名称的第一个“字母”序列化为JSON格式时将其大写,而且单词之间将使用空格分隔:
{
"Id": 1, "First_ Name": "Lokesh", "Last Name": "Gupta", "_Email": "admin@howtodoinjava.com" } 复制代码
默认状况下,Gson会在序列化过程当中忽略null值。可是,有时咱们想序列化具备空值的字段,以便它必须出如今JSON中。为此,可使用serializeNulls()方法:
Employee employeeObj = new Employee(1, "Lokesh", "Gupta", null);
Gson gson = new GsonBuilder() .serializeNulls() .setPrettyPrinting().create(); System.out.println(gson.toJson(employeeObj)); 复制代码
输出:
{
"id": 1, "firstName": "Lokesh", "lastName": "Gupta", "emailId": null } 复制代码
ExclusionStrategy用于肯定是否应将字段或顶级类做为JSON输出/输入的一部分进行序列化或反序列化。
shouldSkipField(attribute)方法也是相同的规则。
在下面的示例中,使用@NPI注解和属于Account类的实例的成员字段不会进行序列化和反序列化。
Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(NPI.class) != null; } @Override public boolean shouldSkipClass(Class<?> clazz) { return clazz.getAnnotation(Account.class) != null; } }) .setPrettyPrinting() .create(); 复制代码
在反序列化期间,Gson使用了一个宽松的JsonReader类。这意味着它仅接受兼容的JSON输入。
若是JSON违反结构规则之一,它将抛出MalformedJsonException。若是咱们将lenient设置为true,则它将忽视某些违规行为,并尝试读取格式不正确的JSON。
Gson gson = new GsonBuilder()
.setLenient() .setPrettyPrinting().create(); 复制代码
使用Gson JsonReader类,该类是基于拉式的流JSON解析器。它有助于将JSON做为令牌流读取。
在流模式下,每一个JSON数据都被视为一个单独的令牌。
当咱们使用JsonReader对其进行处理时,每一个令牌将被顺序处理。例如,
{
"name":"Lokesh" } 复制代码
在使用JsonReader进行解析时,以上JSON将生成4个令牌:
咱们可使用它的简单构造函数建立一个JsonReader实例,该实例接受java.io.Reader类型的输入流。
String json = "{}";
JsonReader jsonReader = new JsonReader( new StringReader(json) ); 复制代码
咱们能够根据JSON流的来源使用如下阅读器之一:
建立包含有效JSON源的JsonReader以后,咱们能够开始遍历流令牌并查看令牌值。
如下是使用JsonReader以令牌形式读取简单JSON的示例:
import java.io.IOException;
import java.io.StringReader; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001,'firstName': 'Lokesh','lastName': 'Gupta','email': null}"; JsonReader jsonReader = new JsonReader(new StringReader(json)); jsonReader.setLenient(true); try { while (jsonReader.hasNext()) { JsonToken nextToken = jsonReader.peek(); if (JsonToken.BEGIN_OBJECT.equals(nextToken)) { jsonReader.beginObject(); } else if (JsonToken.NAME.equals(nextToken)) { String name = jsonReader.nextName(); System.out.println("Token KEY >>>> " + name); } else if (JsonToken.STRING.equals(nextToken)) { String value = jsonReader.nextString(); System.out.println("Token Value >>>> " + value); } else if (JsonToken.NUMBER.equals(nextToken)) { long value = jsonReader.nextLong(); System.out.println("Token Value >>>> " + value); } else if (JsonToken.NULL.equals(nextToken)) { jsonReader.nextNull(); System.out.println("Token Value >>>> null"); } else if (JsonToken.END_OBJECT.equals(nextToken)) { jsonReader.endObject(); } } } catch (IOException e) { e.printStackTrace(); } finally { jsonReader.close(); } } } 复制代码
输出:
Token KEY >>>> id
Token Value >>>> 1001 Token KEY >>>> firstName Token Value >>>> Lokesh Token KEY >>>> lastName Token Value >>>> Gupta Token KEY >>>> email Token Value >>>> null 复制代码
在上面的示例中:
Gson JsonParser用于将Json数据解析为JsonElement的解析树,从而解析为JsonObject。
JsonObject可用于使用JSON字符串中的相应键来访问值。
JsonParser类只有一个默认构造函数,而且不须要任何参数或配置。
JsonParser parser = new JsonParser();
复制代码
JsonParser类提供3种方法来提供JSON做为源并将其解析为JsonElements树。
若是指定的文本不是有效的JSON,则这三个方法都将抛出JsonParseException和JsonSyntaxException。
在JsonElement树中解析了JSON字符串后,咱们就可使用它的各类方法来访问JSON数据元素。
例如,使用一种类型检查方法找出它表明什么类型的JSON元素:
jsonElement.isJsonObject(); jsonElement.isJsonArray(); jsonElement.isJsonNull(); jsonElement.isJsonPrimitive(); 复制代码
咱们可使用相应的方法将JsonElement转换为JsonObject和JsonArray:
JsonObject jsonObject = jsonElement.getAsJsonObject(); JsonArray jsonArray = jsonElement.getAsJsonArray(); 复制代码
一旦有了JsonObject或JsonArray实例,就可使用其get()方法从中提取字段。
使用JsonParser将JSON解析为JsonElement(和JsonObject),并使用键获取JSON值:
import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonParser; public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001, " + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonElement jsonElement = new JsonParser().parse(json); JsonObject jsonObject = jsonElement.getAsJsonObject(); System.out.println( jsonObject.get("id") ); System.out.println( jsonObject.get("firstName") ); System.out.println( jsonObject.get("lastName") ); System.out.println( jsonObject.get("email") ); } } 复制代码
输出:
1001
"Lokesh" "Gupta" "howtodoinjava@gmail.com" 复制代码
咱们可使用Gson实例及其fromJson()方法来得到相同的结果:
String json = "{'id': 1001, "
+ "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class); System.out.println(jsonObject.get("id")); System.out.println(jsonObject.get("firstName")); System.out.println(jsonObject.get("lastName")); System.out.println(jsonObject.get("email")); 复制代码
输出:
String json = "{'id': 1001, "
+ "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com'}"; JsonObject jsonObject = new Gson().fromJson(json, JsonObject.class); System.out.println(jsonObject.get("id")); System.out.println(jsonObject.get("firstName")); System.out.println(jsonObject.get("lastName")); System.out.println(jsonObject.get("email")); 复制代码
这是一个完整的示例,展现了如何迭代从JsonReader得到的JsonElement:
JsonParser parser = new JsonParser();
String json = "{ \"f1\":\"Hello\",\"f2\":{\"f3:\":\"World\"}}"; JsonElement jsonTree = parser.parse(json); if(jsonTree.isJsonObject()){ JsonObject jsonObject = jsonTree.getAsJsonObject(); JsonElement f1 = jsonObject.get("f1"); JsonElement f2 = jsonObject.get("f2"); if(f2.isJsonObject()){ JsonObject f2Obj = f2.getAsJsonObject(); JsonElement f3 = f2Obj.get("f3"); } } 复制代码
Gson在默认序列化和反序列化方面提供了很是出色的功能。
不过,咱们可能会遇到默认和内置自定义选项没法解决咱们问题的状况。在这种状况下,咱们能够经过两个接口JsonSerializer和JsonDeserializer使用自定义序列化和反序列化。
JsonSerializer.java:
public interface JsonSerializer<T> { public JsonElement serialize(T value, Type type, JsonSerializationContext jsonSerializationContext) { } } 复制代码
为Json建立自定义序列化程序后,咱们还须要经过GsonBuilder.registerTypeAdapter(Type,Object)注册该序列化程序。
当Gson遇到指定类型的字段时,它会在序列化期间调用其回调方法serialize()。
假设咱们遇到一种状况,咱们必须将Java对象序列化为json,这样全部布尔值都应写为1或0,而不是打印true或false。
让咱们为该要求编写自定义序列化程序。
BooleanSerializer.java:
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; public class BooleanSerializer implements JsonSerializer<Boolean> { public JsonElement serialize(Boolean aBoolean, Type type, JsonSerializationContext jsonSerializationContext) { if(aBoolean){ return new JsonPrimitive(1); } return new JsonPrimitive(0); } } 复制代码
让咱们编写一个程序,使用registerTypeAdapter()注册JsonSerializer实例,并使用该程序将Java对象序列化为json。
import com.google.gson.Gson;
import com.google.gson.GsonBuilder; public class Main { public static void main(String[] args) throws Exception { Employee emp = new Employee(1, "Lokesh", "Gupta", "howtodoinjava@gmail.com", true); Gson gson = new GsonBuilder() .registerTypeAdapter(Boolean.class, new BooleanSerializer()) .setPrettyPrinting() .create(); String json = gson.toJson(emp); System.out.println(json); } } 复制代码
注意程序输出,键“ active”的值被序列化为1:
{
"id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "active": 1 } 复制代码
定制反序列化器必须实现JsonDeserializer接口。JsonDeserializer接口以下所示:
JsonDeserializer.java:
public interface JsonDeserializer<T> { public Boolean deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException; } 复制代码
为Json建立自定义反序列化器以后,咱们还须要经过GsonBuilder.registerTypeAdapter(Type,Object)注册此反序列化器。
当Gson遇到指定类型的字段时,它会在序列化期间调用其回调方法deserialize()。
假设某些服务将日期字段分别分为天,月和年等部分分别返回给咱们。在JSON字符串中,它们可能有意义,可是在Java中,它们只有做为单个java.time.LocalDate对象的一部分时才有意义。
employee.json:
{
"id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "day": 11, "month": 8, "year": 2019 } 复制代码
咱们要自定义反序列化并将最后三个字段组合为LocalDate对象。
咱们的Employee看起来像这样。包括必要的getter和setter以及构造函数。
Employee.java:
public class Employee { private Integer id; private String firstName; private String lastName; private String email; private LocalDate dob; } 复制代码
自定义反序列化器类以下所示:
EmployeeDeserializer.java:
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; public class EmployeeDeserializer implements JsonDeserializer<Employee> { @Override public Employee deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); LocalDate localDate = LocalDate.of( jsonObject.get("year").getAsInt(), jsonObject.get("month").getAsInt(), jsonObject.get("day").getAsInt() ); return new Employee( jsonObject.get("id").getAsInt(), jsonObject.get("firstName").getAsString(), jsonObject.get("lastName").getAsString(), jsonObject.get("email").getAsString(), localDate); } } 复制代码
注册反序列化器,而后将给定的JSON解析为java对象:
Main.java:
public class Main { public static void main(String[] args) throws Exception { String json = "{'id': 1001," + "'firstName': 'Lokesh'," + "'lastName': 'Gupta'," + "'email': 'howtodoinjava@gmail.com', " + "'day': 11, " + "'month': 8, " + "'year': 2019}"; Gson gson = new GsonBuilder() .registerTypeAdapter(Employee.class, new EmployeeDeserializer()) .create(); Employee employee = gson.fromJson(json, Employee.class); System.out.println(employee); } } 复制代码
注意程序输出将3个单独的字段组合到单个LocalDate对象中:
Employee [id=1001,
firstName=Lokesh, lastName=Gupta, email=howtodoinjava@gmail.com, dob=2019-08-11] 复制代码
参考: 【1】:Gson 【2】:Gson – Introduction 【3】:Gson – Installation 【4】:GSON - Gson 【5】:GSON – Serialize and Deserialize JSON 【6】:Gson – Pretty Printing for JSON Output 【7】:GSON – Parse JSON array to Java array or list 【8】:GSON – Serialize and deserialize JSON to Set 【9】:Gson – GsonBuilder Configuration Examples 【10】:Gson @Since – Version Support 【11】:Gson @SerializedName 【12】:Gson – JsonReader 【13】:Gson – JsonReader 【14】:Gson – JsonParser 【15】:GSON - JsonParser
本文使用 mdnice 排版