原文: 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>{@Overridepublic 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 的自定义序列化和反序列化的问题。
学习愉快!
