原文: https://howtodoinjava.com/gson/custom-serialization-deserialization/
Gson 在默认序列化和反序列化方面提供了非常出色的功能。 不过,我们可能会遇到默认和内置自定义选项无法解决我们问题的情况。
在这种情况下,我们可以使用两个接口JsonSerializer
和JsonDeserializer
使用自定义序列化和反序列化。
1.自定义序列化
1.1 JsonSerializer
接口
JsonSerializer
接口看起来像这样:
public interface JsonSerializer<T>
{
public JsonElement serialize(T value, Type type,
JsonSerializationContext jsonSerializationContext) {
}
}
为 Json 创建自定义序列化器之后,我们还需要通过GsonBuilder.registerTypeAdapter(Type, Object)
注册该序列化器。
Gson 在遇到指定类型的字段时,会在序列化过程中调用其回调方法serialize()
。
1.2 Gson JsonSerializer
示例
假设我们进入一种情况,我们必须将 Java 对象序列化为 json,以便将所有布尔值都写入1 or 0
,而不是打印true or false
。
让我们为该要求编写自定义序列化程序。
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
}
2.自定义反序列化
2.1 JsonDeserializer
接口
自定义反序列化器必须实现JsonDeserializer
接口。 JsonDeserializer
接口如下所示:
public interface JsonDeserializer<T>
{
public Boolean deserialize(JsonElement jsonElement,
Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException;
}
为 Json 创建自定义反序列化器之后,我们还需要通过GsonBuilder.registerTypeAdapter(Type, Object)
注册此反序列化器。
Gson 在遇到指定类型的字段时,会在序列化过程中调用其回调方法deserialize()
。
2.2 Gson JsonDeserializer
示例
假设某些服务将日期字段分别分为天,月和年等部分分别返回给我们。 在 JSON 字符串中,它们可能有意义,但在 Java 中,它们只有作为单个java.time.LocalDate
对象的一部分时才有意义。
{
"id": 1,
"firstName": "Lokesh",
"lastName": "Gupta",
"email": "howtodoinjava@gmail.com",
"day": 11,
"month": 8,
"year": 2019
}
我们要自定义反序列化并将最后三个字段组合为LocalDate
对象。
我们的Employee
看起来像这样。 包括必要的获取器和设置器以及构造器。
public class Employee
{
private Integer id;
private String firstName;
private String lastName;
private String email;
private LocalDate dob;
}
自定义反序列化器类如下所示:
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 对象。
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]
根据提供的 json 输入的保证,我们可能想用has()
来检查JsonObject
中是否存在模型属性。 否则,如果我们正在访问属性,然后尝试获取该属性的值,则可能会遇到NullPointerException
。
向我提供有关 Java 中使用 Gson 的自定义序列化和反序列化的问题。
学习愉快!