多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# Gson – 自定义序列化和反序列化 > 原文: [https://howtodoinjava.com/gson/custom-serialization-deserialization/](https://howtodoinjava.com/gson/custom-serialization-deserialization/) Gson 在默认序列化和反序列化方面提供了非常出色的功能。 不过,我们可能会遇到默认和内置自定义选项无法解决我们问题的情况。 在这种情况下,我们可以使用两个接口`JsonSerializer`和`JsonDeserializer`使用自定义序列化和反序列化。 ## 1.自定义序列化 #### 1.1 `JsonSerializer`接口 [`JsonSerializer`](https://static.javadoc.io/com.google.code.gson/gson/2.8.5/com/google/gson/JsonSerializer.html)接口看起来像这样: ```java 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`。 让我们为该要求编写自定义序列化程序。 ```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。 ```java 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。 ```java { "id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "active": 1 } ``` ## 2.自定义反序列化 #### 2.1 `JsonDeserializer`接口 自定义反序列化器必须实现[`JsonDeserializer`](https://static.javadoc.io/com.google.code.gson/gson/2.8.5/com/google/gson/JsonDeserializer.html)接口。 `JsonDeserializer`接口如下所示: ```java 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`对象的一部分时才有意义。 ```java { "id": 1, "firstName": "Lokesh", "lastName": "Gupta", "email": "howtodoinjava@gmail.com", "day": 11, "month": 8, "year": 2019 } ``` 我们要自定义反序列化并将最后三个字段组合为[`LocalDate`](https://howtodoinjava.com/java/date-time/java-time-localdate-class/)对象。 我们的`Employee`看起来像这样。 包括必要的获取器和设置器以及构造器。 ```java public class Employee { private Integer id; private String firstName; private String lastName; private String email; private LocalDate dob; } ``` 自定义反序列化器类如下所示: ```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 对象。 ```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`对象。 ```java Employee [id=1001, firstName=Lokesh, lastName=Gupta, email=howtodoinjava@gmail.com, dob=2019-08-11] ``` 根据提供的 json 输入的保证,我们可能想用`has()`来检查`JsonObject`中是否存在模型属性。 否则,如果我们正在访问属性,然后尝试获取该属性的值,则可能会遇到`NullPointerException`。 向我提供有关 Java 中使用 Gson 的*自定义序列化和反序列化*的问题。 学习愉快!