You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Jackson自定义反序列化器将多属性转为Validity值对象?

解决Validity自定义反序列化器的实现方案

这个场景我之前处理过,核心就是要让Jackson知道如何从扁平的JSON结构里提取字段,来构建嵌套的Validity值对象。下面是具体的实现步骤和代码示例:

1. 编写Validity的自定义反序列化器

我们需要继承Jackson的StdDeserializer,重写deserialize方法,从父级JSON节点中直接提取validFrom和validTo字段,转换为LocalDate后构建Validity对象:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;
import java.time.LocalDate;

public class ValidityDeserializer extends StdDeserializer<Validity> {

    // 必须的无参构造函数,供Jackson反射调用
    public ValidityDeserializer() {
        this(null);
    }

    protected ValidityDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Validity deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        JsonNode parentNode = parser.getCodec().readTree(parser);
        
        // 从扁平JSON中提取日期字段
        String validFromStr = parentNode.get("validFrom").asText();
        String validToStr = parentNode.get("validTo").asText();
        
        // 转换为LocalDate(如果JSON日期格式非标准,需指定DateTimeFormatter)
        LocalDate validFrom = LocalDate.parse(validFromStr);
        LocalDate validTo = LocalDate.parse(validToStr);
        
        return new Validity(validFrom, validTo);
    }
}

2. 将反序列化器绑定到Validity类

有两种方式可以让Jackson识别这个自定义反序列化器:

方式一:直接在Validity类上添加注解

这种方式更直观,直接在类上标记使用我们的自定义反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.time.LocalDate;

@JsonDeserialize(using = ValidityDeserializer.class)
public class Validity {
    private LocalDate validFrom;
    private LocalDate validTo;

    // 提供无参构造(Jackson默认需要)和全参构造
    public Validity() {}
    
    public Validity(LocalDate validFrom, LocalDate validTo) {
        this.validFrom = validFrom;
        this.validTo = validTo;
    }

    // 省略getter和setter方法
}

方式二:在ObjectMapper中注册反序列化器

如果不想修改Validity类的注解,可以在初始化ObjectMapper时手动注册:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

public class DemoMain {
    public static void main(String[] args) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册JavaTimeModule,支持LocalDate的序列化/反序列化
        objectMapper.registerModule(new JavaTimeModule());
        // 绑定Validity类和自定义反序列化器
        objectMapper.addDeserializer(Validity.class, new ValidityDeserializer());
        
        // 测试反序列化
        String json = "{ \"name\": \"name\", \"validFrom\": \"2018-01-09\", \"validTo\": \"2018-01-10\" }";
        MyPojo myPojo = objectMapper.readValue(json, MyPojo.class);
        
        System.out.println("Name: " + myPojo.getName());
        System.out.println("Valid From: " + myPojo.getValidity().getValidFrom());
        System.out.println("Valid To: " + myPojo.getValidity().getValidTo());
    }
}

3. 确保MyPojo的注解配置正确

你的MyPojo类已经使用了@JsonUnwrapped,这个注解会告诉Jackson:反序列化时把父JSON中的validFrom和validTo字段传递给Validity的反序列化器,刚好和我们的自定义逻辑匹配:

import com.fasterxml.jackson.annotation.JsonUnwrapped;

public class MyPojo {
    private String name;
    @JsonUnwrapped
    private Validity validity;

    // 无参构造和全参构造
    public MyPojo() {}
    
    public MyPojo(String name, Validity validity) {
        this.name = name;
        this.validity = validity;
    }

    // 省略getter和setter方法
}

注意事项

  • 处理LocalDate需要依赖jackson-datatype-jsr310模块,记得在你的依赖管理工具(Maven/Gradle)中引入该依赖。
  • 如果JSON中的日期格式不是标准的yyyy-MM-dd,需要在LocalDate.parse时指定对应的DateTimeFormatter,或者在ObjectMapper中全局配置日期格式。

内容的提问来源于stack exchange,提问作者Patrik Mihalčin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:22:44