Spring Boot控制器中使用MultiMap处理重复键请求的问题
如何让Spring Boot解析含重复键的JSON请求为Guava Multimap
背景信息
请求载荷
正常请求格式:
{ "KeyA": "ValueA", "KeyB": "ValueB", "KeyC": "ValueC", ... "KeyZ": "ValueZ" }
含重复键的请求示例:
{ "KeyA": "ValueA", "KeyA": "ValueA.1", ... }
当前解析代码
Spring Boot控制器接收请求的代码:
@PostMapping public ResponseEntity<Object> createABC( @RequestBody final Map<MyDTO, MyDTO> map ) { // 业务逻辑实现 }
MyDTO的定义:
@Data @ToString(includeFieldNames=false) public class MyDTO implements Comparable<MyDTO> { private final String name; }
问题
原生Java Map会自动对重复键去重,仅保留最后一个键值对。我想用Guava的Multimap来支持重复键,方便后续执行自定义逻辑,但找不到无需修改请求格式、让Spring Boot直接在控制器中解析并接收Multimap的方法。已经配置了ObjectMapper,但仍无法正常接收该结构。
解决步骤
1. 配置Jackson允许重复键
Jackson默认会忽略JSON中的重复键,仅保留最后一个,因此需要先修改ObjectMapper的配置:
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); // 开启允许JSON中存在重复键的特性 objectMapper.configure(JsonParser.Feature.ALLOW_DUPLICATE_NAMES, true); return objectMapper; } }
2. 自定义Multimap反序列化器
编写自定义的JSON反序列化器,将含重复键的JSON结构转换为Guava Multimap:
public class MultimapDeserializer extends JsonDeserializer<Multimap<MyDTO, MyDTO>> { @Override public Multimap<MyDTO, MyDTO> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { Multimap<MyDTO, MyDTO> multimap = ArrayListMultimap.create(); ObjectCodec codec = p.getCodec(); JsonNode rootNode = codec.readTree(p); for (Map.Entry<String, JsonNode> entry : rootNode.fields()) { // 将JSON键转换为MyDTO实例 MyDTO key = new MyDTO(entry.getKey()); // 将JSON值转换为MyDTO实例 MyDTO value = new MyDTO(entry.getValue().asText()); multimap.put(key, value); } return multimap; } }
3. 在控制器中使用Multimap
修改控制器参数,指定使用自定义反序列化器:
@PostMapping public ResponseEntity<Object> createABC( @RequestBody @JsonDeserialize(using = MultimapDeserializer.class) final Multimap<MyDTO, MyDTO> multimap ) { // 此时multimap已包含所有重复键的键值对,可执行自定义业务逻辑 return ResponseEntity.ok().build(); }
补充说明
如果MyDTO存在复杂的序列化/反序列化规则,确保Jackson能正确将JSON字符串转换为MyDTO实例即可,无需额外修改反序列化器逻辑。
内容的提问来源于stack exchange,提问作者Neill Lima
相关产品推荐
相关产品推荐

