17370845950

如何在不定义请求类的情况下灵活处理动态 JSON 请求体(含数组字段)

本文介绍在 spring boot 中不依赖固定 dto 类,直接解析并操作任意结构的 json 请求体,尤其支持字符串、数组等混合类型字段的动态处理方案。

在实际开发中,API 接口常需接收结构不确定的请求体(如配置项、扩展字段、多租户自定义属性等)。若强行用 HashMap 接收,会因类型擦除导致无法正确反序列化数组(如 "empAwardsReceived": ["On the spot award", "Best employee award"])——该字段将被转为 JSON 字符串而非 List,丧失结构语义与后续操作能力。

推荐方案:以原始 JSON 字符串接收 + Jackson 动态树模型解析

@PostMapping("/employees")
public ResponseEntity getEmployees(@RequestBody String rawJson) {
    ObjectMapper mapper = new ObjectMapper();
    try {
        JsonNode rootNode = mapper.readTree(rawJson);

        // ✅ 安全读取字符串字段(自动处理缺失/空值)
        String employeeId = rootNode.path("employeeId").asText("");
        String empName = rootNode.path("empName").asText("");

        // ✅ 正确读取字符串数组(即使字段不存在也返回空列表)
        List awards = new ArrayList<>();
        JsonNode awardsNode = rootNode.path("empAwardsReceived");
        if (awardsNode.isArray()) {
            awardsNode.forEach(node -> awards.add(node.asText()));
        }

        // ✅ 动态添加新字段(例如注入时间戳或服务端计算值)
        ((ObjectNode) rootNode).put("processedAt", Instant.now().toString());

        // 后续业务逻辑...
        EmployeeResponse response = processEmployee(employeeId, empName, awards);
        return ResponseEntity.ok(response);

    } catch (JsonProcessingException e) {
        return ResponseEntity.badRequest()
                .body(new EmployeeResponse("Invalid JSON format"));
    }
}

关键要点说明:

  • 使用 @RequestBody String 避免 Spring MVC 的自动类型转换限制,保留原始 JSON 结构;
  • JsonNode 是 Jackson 的不可变树模型,path() 方法安全访问嵌套字段(无 NPE 风险);
  • isArray() + forEach() 精准识别并遍历数组节点,避免 asText() 错误转义;
  • 通过强转为 ObjectNode 可动态增删改节点,满足运行时修改需求;
  • ⚠️ 注意:生产环境建议配合 @Validated 或自定义校验注解对关键字段做存在性/格式校验,避免过度依赖动态解析带来的隐式错误。

此方案兼顾灵活性与健壮性,无需为每个动态接口维护 DTO,同时完整支持 JSON 全类型(对象、数组、布尔、数字),是微服务网关、低代码平台、配置中心等场景的理想实践。