使用Jackson ObjectMapper反序列化JSON字符串时遭遇InvalidFormatException异常的求助
解决Jackson反序列化空字符串到LinkedHashMap的错误
我来帮你分析下这个问题并给出可行的解决方案:
首先,你的JSON字符串里comments字段的值是空字符串"",但你尝试反序列化到Map<String, LinkedHashMap>类型时,Jackson默认无法将空字符串转换为LinkedHashMap对象,所以抛出了InvalidFormatException。
你的JSON数据:
{"id" : "1234", "name" : "Name", "description" : "abcd\n\rdghsdghjdg", "risk" : "LOW", "status" : "Open", "autoGenerated" : false, "comments" : "", "category" : [ "abc", "def" ], "lastModifiedDate" : "2021-11-19T11:23:04.948074Z", "lastModifiedBy" : "amallik", "readableId" : "2553", "componentBlocks" : [ ], "threatTemplateId" : "5678", "threatTags" : [ ], "threatComponents" : [ ], "components" : { "blocks" : [ ], "lines" : [ ], "connections" : [ ] }, "mitigationList" : [ { "mitigationTemplateId" : "155", "title" : "abcd", }, { "mitigationTemplateId" : "152", "title" : "efgh", }, { "mitigationTemplateId" : "153", "title" : "ijkl", }], "rejected" : false, "edited" : true }
你使用的反序列化代码:
ObjectMapper mapper = new ObjectMapper(); mapper.readValue(currentPayload, new TypeReference<Map<String, LinkedHashMap>>(){});
报错信息:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("") to element of `java.util.LinkedHashMap<java.lang.Object,java.lang.Object>` (but could if coercion was enabled using `CoercionConfig`) at [Source: (String)"{ [truncated chars]; line: 8, column: 16] (through reference chain: java.util.LinkedHashMap["comments"])
解决方案
1. 改用更通用的Map<String, Object>类型
你的JSON包含多种类型的值(字符串、布尔、数组、嵌套对象),用Object作为值类型可以兼容所有情况,空字符串也能正常解析:
ObjectMapper mapper = new ObjectMapper(); Map<String, Object> threatMap = mapper.readValue(currentPayload, new TypeReference<Map<String, Object>>(){});
2. 配置Jackson允许空字符串转成空Map
如果你坚持要用LinkedHashMap作为值类型,可以通过配置Jackson的强制转换规则,让空字符串被处理为空的LinkedHashMap:
ObjectMapper mapper = new ObjectMapper(); // 配置将空字符串强制转换为空的Map mapper.coercionConfigFor(LogicalType.Map) .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); Map<String, LinkedHashMap> threatMap = mapper.readValue(currentPayload, new TypeReference<Map<String, LinkedHashMap>>(){});
3. 创建对应的实体类(推荐方案)
如果这个JSON结构是固定的,最稳妥的方式是创建匹配的Java实体类,这样类型安全,后续操作也更方便:
import java.util.List; public class Threat { private String id; private String name; private String description; private String risk; private String status; private boolean autoGenerated; private String comments; // 直接用String类型对应空字符串 private List<String> category; private String lastModifiedDate; private String lastModifiedBy; private String readableId; private List<Object> componentBlocks; private String threatTemplateId; private List<Object> threatTags; private List<Object> threatComponents; private Components components; private List<Mitigation> mitigationList; private boolean rejected; private boolean edited; // Getters and Setters public static class Components { private List<Object> blocks; private List<Object> lines; private List<Object> connections; // Getters and Setters } public static class Mitigation { private String mitigationTemplateId; private String title; // Getters and Setters } }
然后反序列化时直接使用这个实体类:
ObjectMapper mapper = new ObjectMapper(); Threat threat = mapper.readValue(currentPayload, Threat.class);
这样comments字段作为String类型,空字符串就能被正确解析,而且整个数据结构的类型更清晰,避免了Map类型带来的类型转换问题。
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

