fasterxml jackson反序列化时对于非静态内部类报错问题及解决

 更新时间:2023年08月10日 11:36:13   作者:赶路人儿  
这篇文章主要介绍了fasterxml jackson反序列化时对于非静态内部类报错问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

fasterxml jackson反序列化时对于非静态内部类报错

java中通常使用jackson、fastjson两个库来处理json。后者的api使用起来比较方便,但是安全漏洞太多了。

在使用jackson反序列化json字符串时,遇到了一个问题:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `json.TransferResp$TransforData` (although at least one Creator exists): can only instantiate non-static inner class by using default, no-argument constructor

很多文章没有解释清楚,本文做了一个实验。

对于嵌套结构,定义了一个包含内部类的java类来接收,如果这个复杂结构是一个数组形式,那么反序列化时会报上面错误。

实验一

1)java实体类

@Data
public class TransforResponse {
    private Integer code;
    private Map<String, String> defaultData;
    private TransforData data;
    @Data
    public static class TransforData{
        private Long encyId;
        private int score;
        private Map<String, String> other;
    }
}

2)测试

private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) throws Exception {
    String jsonStr = serialization(); //{\"code\":200,\"data\":{\"encyId\":123,\"other\":{\"a\":\"test\"},\"score\":5}}
    deSerialization(jsonStr); //TransferResp(code=200, data=TransferResp.TransforData(encyId=123, score=5, other={a=test}))
    System.out.println("----------");
    String jsonStr2 = serialization2(); //{\"code\":200,\"data\":{\"encyId\":123,\"other\":{\"a\":\"test\"},\"score\":5}}
    deSerialization2(jsonStr2); //TransferResp(code=200, data=TransferResp.TransforData(encyId=123, score=5, other={a=test}))
}
private static TransferResp createObj() {
    TransferResp tr = new TransferResp();
    TransforData transforData = tr.new TransforData();
    transforData.setEncyId(123L);
    transforData.setScore(5);
    Map<String, String> hashMap = new HashMap<>(1);
    hashMap.put("a", "test");
    transforData.setOther(hashMap);
    tr.setCode(200);
    tr.setData(transforData);
    return tr;
}
private static String serialization() {
    TransferResp tr = createObj();
    String jsonString = JSONObject.toJSONString(tr);
    System.out.println(jsonString);
    return jsonString;
}
private static void deSerialization(String jsonStr) {
    TransferResp parseObject = JSONObject.parseObject(jsonStr, TransferResp.class);
    System.out.println(parseObject.toString());
}
private static String serialization2() throws JsonProcessingException {
    TransferResp tr = createObj();
    String jsonString = objectMapper.writeValueAsString(tr);
    System.out.println(jsonString);
    return jsonString;
}
private static void deSerialization2(String jsonStr) throws JsonParseException, JsonMappingException, IOException {
    TransferResp parseObject = objectMapper.readValue(jsonStr, TransferResp.class);
    System.out.println(parseObject.toString());
}

运行后正常。

实验二

1)java实体类

@Data
public class TransferResp {
    private Integer code;
    private List<TransforData> data;
    @Data
    public class TransforData{
        private Long encyId;
        private Integer score;
        private Map<String, String> other;
    }
}

2)测试

private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) throws Exception {
    String jsonStr = serialization(); //{"code":200,"data":[{"encyId":123,"other":{"a":"test"},"score":5}]}
    deSerialization(jsonStr); //TransferResp(code=200, data=[TransferResp.TransforData(encyId=123, score=5, other={a=test})])
    System.out.println("----------");
    String jsonStr2 = serialization2(); //{"code":200,"data":[{"encyId":123,"score":5,"other":{"a":"test"}}]}
    deSerialization2(jsonStr2); //error
}
private static TransferResp createObj() {
    TransferResp tr = new TransferResp();
    TransforData transforData = tr.new TransforData();
    transforData.setEncyId(123L);
    transforData.setScore(5);
    Map<String, String> hashMap = new HashMap<>(1);
    hashMap.put("a", "test");
    transforData.setOther(hashMap);
    List<TransforData> list = new ArrayList<>();
    list.add(transforData);
    tr.setCode(200);
    tr.setData(list);
    return tr;
}
private static String serialization() {
    TransferResp tr = createObj();
    String jsonString = JSONObject.toJSONString(tr);
    System.out.println(jsonString);
    return jsonString;
}
private static void deSerialization(String jsonStr) {
    TransferResp parseObject = JSONObject.parseObject(jsonStr, TransferResp.class);
    System.out.println(parseObject.toString());
}
private static String serialization2() throws JsonProcessingException {
    TransferResp tr = createObj();
    String jsonString = objectMapper.writeValueAsString(tr);
    System.out.println(jsonString);
    return jsonString;
}
private static void deSerialization2(String jsonStr) throws JsonParseException, JsonMappingException, IOException {
    TransferResp parseObject = objectMapper.readValue(jsonStr, TransferResp.class);
    System.out.println(parseObject.toString());
}

运行时会报错:

Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `json.TransferResp$TransforData` (although at least one Creator exists): can only instantiate non-static inner class by using default, no-argument constructor

3)解决方法

A、使用静态内部类

@Data
public class TransferResp {
    private Integer code;
    private List<TransforData> data;
    @Data
    public static class TransforData{
        private Long encyId;
        private Integer score;
        private Map<String, String> other;
    }
}

B)将内部类定义在一个单独的类文件中。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot自动重启、热启动方式

    SpringBoot自动重启、热启动方式

    这篇文章主要介绍了SpringBoot自动重启、热启动方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • JavaWeb文件上传下载功能示例解析

    JavaWeb文件上传下载功能示例解析

    这篇文章主要介绍了JavaWeb中的文件上传和下载功能的实现,文件上传和下载功能是非常常用的功能,需要的朋友可以参考下
    2016-06-06
  • Mybatis实现动态增删改查功能的示例代码

    Mybatis实现动态增删改查功能的示例代码

    这篇文章主要介绍了Mybatis实现动态增删改查功能的示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • 使用MQ消息队列的优缺点详解

    使用MQ消息队列的优缺点详解

    这篇文章主要介绍了使用MQ消息队列的优缺点详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • springboot 使用clickhouse实时大数据分析引擎(使用方式)

    springboot 使用clickhouse实时大数据分析引擎(使用方式)

    这篇文章主要介绍了springboot 使用clickhouse实时大数据分析引擎的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2022-02-02
  • Mybatis中foreach标签带来的空格\换行\回车问题及解决方案

    Mybatis中foreach标签带来的空格\换行\回车问题及解决方案

    这篇文章主要介绍了解决Mybatis中foreach标签带来的空格,换行,回车问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • 使用Maven配置Spring的方法步骤

    使用Maven配置Spring的方法步骤

    这篇文章主要介绍了使用Maven配置Spring的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • Springboot分模块项目搭建的实现

    Springboot分模块项目搭建的实现

    在软件开发中,利用Spring Boot进行分模块项目搭建能够提高代码的模块化和复用性,本文主要介绍了Springboot分模块项目搭建的实现,感兴趣的可以了解一下
    2024-10-10
  • Java使用EasyExcel动态修改模板Sheet名称的具体方案

    Java使用EasyExcel动态修改模板Sheet名称的具体方案

    在使用 EasyExcel 通过模板导出时,模板中的 sheet 名称通常是固定的,如果我们希望在导出时根据业务需要 动态修改 sheet 名称,可以通过自定义 SheetWriteHandler 完成,所以本文介绍了Java使用EasyExcel动态修改模板Sheet名称的具体方案,需要的朋友可以参考下
    2025-12-12
  • 利用java反射机制调用类的私有方法(推荐)

    利用java反射机制调用类的私有方法(推荐)

    下面小编就为大家带来一篇利用java反射机制调用类的私有方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08

最新评论