You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:54:24