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)将内部类定义在一个单独的类文件中。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。