Jackson 解决没有无参构造函数的反序列化问题

文章目录

1. 问题

在对外部代码或项目中明确不能提供无参构造函数的实例进行反序列化时,Jackson 会报找不到构造器的错误提示信息。那么如何在不修改代码的前提下实现反序列呢?

2. 解决方案

2.1 实现反序列化器

Response

Response 对象没有提供无参构造函数,但是要实现反序列化功能。

java 复制代码
@Setter
@Getter
public class Response {
    private Map<String, String> headerMap;
    private Map<String, String> apiMap;

    public Response(Map<String, String> headerMap, Map<String, String> apiMap) {
        this.headerMap = headerMap;
        this.apiMap = apiMap;
    }
}
ResponseDeserializer

此时,可以通过实现 JsonDeserializer<Response> 接口,实现自定义反序列化器。

java 复制代码
public class ResponseDeserializer extends JsonDeserializer<Response> {
    @Override
    public Response deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        Map<String, Map<String, String>> map = jsonParser.readValueAs(Map.class);
        Map<String, String> headerMap = map.get("headerMap");
        Map<String, String> apiMap = map.get("apiMap");

        return new Response(headerMap, apiMap);
    }
}
ObjectMapperUtil

将反序列化器注册到 ObjectMapper 中:

java 复制代码
public class ObjectMapperUtil {
    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        SimpleModule simpleModule = new SimpleModule("custom");
        simpleModule.addDeserializer(Response.class, new ResponseDeserializer());
        objectMapper.registerModule(simpleModule);
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     *
     * @param object
     * @return
     */
    public static String writeAsPrettyString(Object object) {
        try {
            return getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

2.2 通过 MIXMIN 和 @JsonCreator机制实现

ResponseMixin

首先实现 @JsonCreator 功能的构造器:

java 复制代码
public class ResponseMixin {
    @JsonCreator
    public ResponseMixin(@JsonProperty("headerMap")Map<String, String> headerMap,
                         @JsonProperty("apiMap")Map<String, String> apiMap) {
    }
}

3. 测试

ResponseTest
java 复制代码
// Jackson 解决没有无参构造函数的反序列化问题 - https://segmentfault.com/a/1190000041734426
public class ResponseTest {

    @Test
    public void testUseSelfDeserializeWithoutNoArgsConstructor() throws JsonProcessingException {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Content-Length", "123");
        Map<String, String> apiMap = new HashMap<>();
        apiMap.put("user", "用户");
        apiMap.put("admin", "管理员");
        Response response = new Response(headerMap, apiMap);
        String jsonStr = ObjectMapperUtil.getObjectMapper().writeValueAsString(response);
        System.out.println(jsonStr);

        response = ObjectMapperUtil.getObjectMapper().readValue(jsonStr, Response.class);
        System.out.println(response != null);
    }
    @Test
    public void testUseMixin() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.addMixIn(Response.class, ResponseMixin.class);

        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Content-Type", "application/json");
        headerMap.put("Content-Length", "123");
        Map<String, String> apiMap = new HashMap<>();
        apiMap.put("user", "用户");
        apiMap.put("admin", "管理员");
        Response response = new Response(headerMap, apiMap);
        String jsonStr = objectMapper.writeValueAsString(response);
        System.out.println(jsonStr);

        response = objectMapper.readValue(jsonStr, Response.class);
        System.out.println(response != null);
    }
}
相关推荐
阿俊-全栈开发21 小时前
LikeShop 单商户SaaS商城分销模块二开:佣金计算与结算逻辑实现
java·开发语言·微服务·likeshop·likeshop开源商城·likeshop多商户
wuminyu1 天前
C++协程实现接收端的零拷贝Buffer管理原理剖析
java·linux·c语言·jvm·c++
蜗牛互联网1 天前
WSL Containers GA:本地AI容器的生命周期、网络与治理验收
java·网络·人工智能·后端
龙亘川1 天前
铭记英烈守初心,数字强基促服务:亘川智城退役军人服务系统的实践与价值
java·数据库·人工智能
OxYGC1 天前
[AI工程] Spring AI 第廿一篇:存量 REST 接口的 MCP 化改造实录——工具从哪条路径注册、参数描述怎么写、身份怎么过去
java·人工智能·spring
Zhou1411361 天前
SpringBoot_02_自动配置原理
java·spring boot·后端
FYKJ_20101 天前
SSM校园失物招领系统41452-计算机课程设计、毕业设计
java·vue.js·spring boot·python·mysql·typescript·spark
kv1101 天前
Android studio国内开发有关
java·数据库·android studio
卓怡学长1 天前
w198基于springboot始于足下健康打卡平台的设计与实现
java·spring boot·spring·intellij-idea
阿狗童鞋1 天前
Java并发编程实战指南
java·开发语言