jackson自定义反序列化器

1,086 阅读3分钟

@JsonDeserialize(using = JsonTypeDeserializer.class) 是 Jackson 库中的一个注解,用于指定在反序列化过程中使用自定义的反序列化器(JsonTypeDeserializer)。通过这个注解,你可以控制如何将 JSON 数据转换为 Java 对象。

以下是如何使用 @JsonDeserialize(using = JsonTypeDeserializer.class) 的详细说明和示例。


1. 使用场景

  • 当默认的 Jackson 反序列化行为无法满足需求时。
  • 当 JSON 数据结构复杂,需要自定义解析逻辑时。
  • 当需要在反序列化过程中进行数据转换或验证时。

2. 实现步骤

步骤 1:定义目标类

假设你有一个类 MyClass,你希望使用自定义的反序列化器来反序列化它。

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = JsonTypeDeserializer.class) // 指定自定义反序列化器
public class MyClass {
    private String name;
    private int value;

    // 必须有无参构造函数
    public MyClass() {}

    // Getter 和 Setter 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "MyClass{name='" + name + "', value=" + value + "}";
    }
}

步骤 2:实现自定义反序列化器

创建一个自定义反序列化器 JsonTypeDeserializer,继承 JsonDeserializer<T> 并实现 deserialize 方法。

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;

public class JsonTypeDeserializer extends JsonDeserializer<MyClass> {

    @Override
    public MyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 将 JSON 数据解析为 JsonNode
        JsonNode node = p.getCodec().readTree(p);

        // 从 JsonNode 中提取字段值
        String name = node.get("name").asText(); // 获取 "name" 字段
        int value = node.get("value").asInt();   // 获取 "value" 字段

        // 创建目标对象并设置值
        MyClass myClass = new MyClass();
        myClass.setName(name);
        myClass.setValue(value);

        // 返回反序列化后的对象
        return myClass;
    }
}

步骤 3:反序列化 JSON 数据

使用 Jackson 的 ObjectMapper 将 JSON 字符串反序列化为 MyClass 对象。

import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) throws Exception {
        // JSON 字符串
        String json = "{"name":"John", "value":30}";

        // 创建 ObjectMapper
        ObjectMapper mapper = new ObjectMapper();

        // 反序列化 JSON 到 MyClass 对象
        MyClass myClass = mapper.readValue(json, MyClass.class);

        // 输出结果
        System.out.println(myClass); // 输出: MyClass{name='John', value=30}
    }
}

3. 关键点说明

  1. @JsonDeserialize 注解

    • 用于类或字段上,指定自定义反序列化器。
    • using 属性指定反序列化器的类。
  2. 自定义反序列化器

    • 继承 JsonDeserializer<T>,其中 T 是目标类型。
    • 实现 deserialize 方法,解析 JsonParser 中的数据并返回目标对象。
  3. ObjectMapper

    • 是 Jackson 的核心类,用于序列化和反序列化 JSON 数据。
    • 通过 readValue 方法将 JSON 字符串转换为 Java 对象。

4. 复杂示例:嵌套对象或数组

如果 JSON 数据更复杂(例如包含嵌套对象或数组),可以在自定义反序列化器中进一步解析。

示例 JSON

{
  "name": "John",
  "value": 30,
  "details": {
    "address": "123 Main St",
    "city": "New York"
  }
}

自定义反序列化器

@Override
public MyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
    JsonNode node = p.getCodec().readTree(p);

    String name = node.get("name").asText();
    int value = node.get("value").asInt();

    // 解析嵌套对象
    JsonNode detailsNode = node.get("details");
    String address = detailsNode.get("address").asText();
    String city = detailsNode.get("city").asText();

    MyClass myClass = new MyClass();
    myClass.setName(name);
    myClass.setValue(value);
    myClass.setAddress(address);
    myClass.setCity(city);

    return myClass;
}

5. 总结

  • @JsonDeserialize(using = JsonTypeDeserializer.class) 是一种强大的工具,用于自定义 Jackson 的反序列化行为。
  • 通过实现 JsonDeserializer,你可以完全控制如何将 JSON 数据映射到 Java 对象。
  • 适用于处理复杂 JSON 结构、数据转换或验证等场景。

如果你有更多问题或需要进一步的帮助,请随时提问!