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

学习愉快！