Gson – 自定义序列化和反序列化

Gson – 自定义序列化和反序列化

原文: https://howtodoinjava.com/gson/custom-serialization-deserialization/

Gson 在默认序列化和反序列化方面提供了非常出色的功能。 不过,我们可能会遇到默认和内置自定义选项无法解决我们问题的情况。

在这种情况下,我们可以使用两个接口JsonSerializerJsonDeserializer使用自定义序列化和反序列化。

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 的自定义序列化和反序列化的问题。

学习愉快!