使用Jackson ObjectMapper将MultivaluedMap转换为POJO时抛出异常
这个问题我之前也碰到过!根源在于MultivaluedMap的结构是键对应值的列表(ListMismatchedInputException,提示无法从START_ARRAY token反序列化出String。
下面给你几个实用的解决方案,按需选择:
方案一:手动转成单值Map(最直接,适合确定每个键只有一个值的场景)
既然MultivaluedMap每个键对应的是列表,那我们先把它转成普通的Map<String, String>,取每个列表的第一个元素,再用Jackson转换:
public void process(MultivaluedMap<String, String> formParams) { ObjectMapper objectMapper = new ObjectMapper(); // 把MultivaluedMap转成单值Map Map<String, String> singleValueMap = new HashMap<>(); for (Map.Entry<String, List<String>> entry : formParams.entrySet()) { List<String> values = entry.getValue(); if (values != null && !values.isEmpty()) { singleValueMap.put(entry.getKey(), values.get(0)); } // 如果需要处理空列表,可以加else逻辑赋值null或者默认值 } final MyPojo myPojo = objectMapper.convertValue(singleValueMap, MyPojo.class); }
方案二:自定义Jackson反序列化器(自动处理数组转单值)
如果不想手动转Map,可以给POJO的字段加自定义反序列化器,让Jackson自动把数组转成第一个元素的字符串:
首先写一个通用的反序列化器:
public class ListToStringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.readValueAsTree(); // 如果是数组,取第一个元素;如果是字符串直接返回;否则返回null if (node.isArray() && node.size() > 0) { return node.get(0).asText(); } else if (node.isTextual()) { return node.asText(); } return null; } }
然后在POJO的字段上加上@JsonDeserialize注解:
@AllArgsConstructor @NoArgsConstructor @Getter @Setter @JsonIgnoreProperties(ignoreUnknown = true) public class MyPojo { private String status; @JsonProperty("order_no") @JsonDeserialize(using = ListToStringDeserializer.class) private String orderId; @JsonProperty("tid") @JsonDeserialize(using = ListToStringDeserializer.class) private String transactionId; }
这样原来的convertValue代码就可以直接用了,Jackson会自动处理列表到单值的转换。
方案三:使用Jackson的JAX-RS模块(适合JAX-RS环境)
如果你的项目本来就用JAX-RS,可以引入jackson-datatype-jaxrs模块,它内置了MultivaluedMap的处理逻辑:
先加Maven依赖:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jaxrs</artifactId> <version>${jackson.version}</version> </dependency>
然后注册模块到ObjectMapper:
public void process(MultivaluedMap<String, String> formParams) { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule(new JaxrsModule()); final MyPojo myPojo = objectMapper.convertValue(formParams, MyPojo.class); }
这个模块会自动处理MultivaluedMap的value列表,把它转成适合POJO单值字段的格式。
内容的提问来源于stack exchange,提问作者Robert Strauch
相关产品推荐
相关产品推荐

