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

配置Jackson序列化/反序列化以兼容Immutables类

配置Jackson自动适配Immutables类

不需要给每个带@Value.Immutable的接口手动添加@JsonDeserialize和@JsonSerialize注解,你可以通过自定义Jackson Module实现自动绑定对应的Immutable实现类,具体步骤如下:

1. 实现自定义类型解析器

这个解析器负责检测带有@Value.Immutable注解的抽象类型,并找到对应的Immutable实现类:

import com.fasterxml.jackson.databind.AbstractTypeResolver;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.SerializationConfig;
import org.immutables.value.Value;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class ImmutablesTypeResolver extends AbstractTypeResolver {
    @Override
    public Class<?> findTypeMapping(SerializationConfig config, BeanDescription typeDesc) {
        return findImmutableImpl(typeDesc.getBeanClass());
    }

    @Override
    public Class<?> findTypeMapping(DeserializationConfig config, BeanDescription typeDesc) {
        return findImmutableImpl(typeDesc.getBeanClass());
    }

    private Class<?> findImmutableImpl(Class<?> abstractType) {
        // 仅处理带有@Value.Immutable注解的类型
        if (!abstractType.isAnnotationPresent(Value.Immutable.class)) {
            return null;
        }

        String simpleName = abstractType.getSimpleName();
        String implSimpleName = "Immutable" + simpleName;
        String implClassName;

        // 处理内部类和普通类的类名拼接
        if (abstractType.isMemberClass()) {
            implClassName = abstractType.getName().replace(simpleName, implSimpleName);
        } else {
            implClassName = abstractType.getPackage().getName() + "." + implSimpleName;
        }

        try {
            Class<?> implClass = Class.forName(implClassName);
            // 验证实现类的合法性:是抽象类型的子类、且为final类(Immutables生成类的特征)
            if (abstractType.isAssignableFrom(implClass) && Modifier.isFinal(implClass.getModifiers())) {
                // 检查是否有私有构造器(Immutables生成类的构造器为私有,通过builder创建)
                for (Constructor<?> c : implClass.getDeclaredConstructors()) {
                    if (Modifier.isPrivate(c.getModifiers())) {
                        return implClass;
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            // 找不到实现类时返回null,Jackson将按默认逻辑处理
            return null;
        }
        return null;
    }
}

2. 创建自定义Jackson Module

将上面的类型解析器注册到Module中:

import com.fasterxml.jackson.databind.module.SimpleModule;

public class ImmutablesJacksonModule extends SimpleModule {
    public ImmutablesJacksonModule() {
        super("ImmutablesJacksonModule");
        addAbstractTypeResolver(new ImmutablesTypeResolver());
    }
}

3. 注册Module到ObjectMapper

在配置Jackson的ObjectMapper时,注册这个自定义Module:

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonConfig {
    public static ObjectMapper createObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 注册Immutables自动适配模块
        objectMapper.registerModule(new ImmutablesJacksonModule());
        
        // 可添加其他Jackson配置,比如忽略未知属性
        objectMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        
        return objectMapper;
    }
}

注意事项

  • 确保项目已正确配置Immutables注解处理器,编译时能生成ImmutableXxx实现类
  • 若接口存在嵌套类结构,上述代码已处理Outer.Foo对应Outer.ImmutableFoo的情况
  • 如果实现类的命名规则不是Immutable+原类名,需要调整implSimpleName的生成逻辑

内容的提问来源于stack exchange,提问作者Mark Elliot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:33:16