前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” !!!

06-01 1317阅读

🚀 前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” 🌟

嘿,技术冒险家们!👋 今天我们要聊一个开发中常见的“坑”:前端传来的 JSON 参数字段名和后端对象字段名不一致,会发生什么?是默默失败,还是直接炸裂?💥 我将以 Spring 的 PageWithSearch 为例,带你揭开 Jackson 的神秘面纱,还有流程图助阵,快跟我一起探索吧!💪


🎯 第一幕:一场“命名失误”的意外

问题起源

我在开发一个分页查询接口,前端传了个 JSON:

{
  "searchField": "name",
  "searchValue": "John",
  "pageNum": 0,
  "pageSize": 10
}

后端用 PageWithSearch 接收:

@PostMapping("/listInviteCodeByPageWithSearch")
public BaseResult listInviteCodeByPageWithSearch(
        @Valid @RequestBody PageWithSearch pageWithSearch) {
    Page inviteCodePage = inviteCodeService.findPaginatedInviteCodeByAdminIdAndSearch(7, pageWithSearch);
    return BaseResult.success(inviteCodePage);
}

结果,服务层抛了个 NullPointerException,接口返回:

{
  "code": 500,
  "msg": "分页查询失败:null",
  "data": null
}

啥?明明传了 pageNum 和 pageSize,怎么炸了?🤔


🔍 第二幕:深入代码,寻找线索

关键代码

服务层:

public Page findPaginatedInviteCodeByAdminIdAndSearch(Integer adminId, PageWithSearch pageWithSearch) {
    PageRequest pageRequest = PageRequest.of(pageWithSearch.getPage(), pageWithSearch.getPageSize());
    // ... 其他逻辑 ...
}

PageWithSearch 和 BasePage:

public class PageWithSearch extends BasePage {
    private String field;
    private String value;
    public Integer getPageSize() {
        return this.size;
    }
}
public class BasePage {
    Integer page;
    Integer size;
    public Integer getPage() {
        return page;
    }
    public Integer getSize() {
        return size;
    }
}

初步分析

  • 前端字段:pageNum、pageSize。
  • 后端字段:page、size。
  • 问题:字段名不一致,pageWithSearch.getPage() 和 getPageSize() 返回 null,导致 PageRequest.of 自动拆箱时抛出 NullPointerException。

    🐞 第三幕:Jackson 的“严格规则”

    真相揭晓

    Spring 默认用 Jackson 处理 JSON 到对象的映射,它的规则很简单:

    • 字段名必须一致:JSON 字段名与 Java 对象字段名大小写敏感匹配。
    • 不一致的结果:未匹配的字段被忽略,对象中对应字段保持默认值(null)。
      测试验证

      输入:

      {
        "pageNum": 0,
        "pageSize": 10
      }
      
      • pageWithSearch.getPage() → null(无 page 字段)。
      • pageWithSearch.getPageSize() → null(无 size 字段)。
      • PageRequest.of(null, null) → 自动拆箱 → NullPointerException。
        Mermaid 流程图:映射失败过程

        🔧 第四幕:解决“命名冲突”

        为什么会这样?

        • Jackson 的默认行为:严格匹配,不做自动转换。
        • 后端代码:未处理字段名不一致,导致 null 值引发下游问题。

          解决方案

          方案 1:用 @JsonProperty 指定映射

          修改 BasePage 和 PageWithSearch:

          public class BasePage {
              @JsonProperty("pageNum")
              Integer page;
              @JsonProperty("pageSize")
              Integer size;
              // ... 其他代码 ...
          }
          public class PageWithSearch extends BasePage {
              @JsonProperty("searchField")
              private String field;
              @JsonProperty("searchValue")
              private String value;
              // ... 其他代码 ...
          }
          
          • 效果:
            • 前端用 pageNum、pageSize、searchField,后端正确映射。
            • 输入:
              {
                "searchField": "name",
                "pageNum": 0,
                "pageSize": 10
              }
              
              • pageWithSearch.getPage() → 0
              • pageWithSearch.getPageSize() → 10
                方案 2:全局命名策略

                在 application.yml 中配置:

                spring:
                  jackson:
                    property-naming-strategy: SNAKE_CASE
                
                • 效果:
                  • 前端用 page_num、page_size,自动映射到 page、size。
                  • 输入:
                    {
                      "field": "name",
                      "page_num": 0,
                      "page_size": 10
                    }
                    
                    方案 3:服务层防御

                    即使字段名不一致,也避免异常:

                    public Page findPaginatedInviteCodeByAdminIdAndSearch(Integer adminId, PageWithSearch pageWithSearch) {
                        Pageable pageable = pageWithSearch.toPageableWithDefault(0, 10); // 默认值保护
                        String field = pageWithSearch.getField();
                        String value = pageWithSearch.getValue();
                        if (!StringUtils.isEmpty(field) && !StringUtils.isEmpty(value)) {
                            return inviteCodeRepository.findPaginatedInviteCodeByAdminIdAndFieldAndValue(adminId, field, value, pageable);
                        } else {
                            return inviteCodeRepository.findByAdminId(adminId, pageable);
                        }
                    }
                    
                    • 效果:
                      • page 或 size 为 null 时,用默认值 0 和 10。
                        Mermaid 流程图:修复过程

                        🌈 第五幕:经验与启发

                        学到了啥?💡

                        1. Jackson 的严格匹配:
                          • 字段名不一致,后端字段变 null,小心下游逻辑!
                          • 命名约定很重要:
                            • 前后端要统一字段名,或者用工具桥接差异。
                            • 防御性编程:
                              • null 是隐患,提前处理是王道。

                        小建议 🌟

                        • 文档化:
                          • 用 Swagger 或 API 文档明确字段名,减少误解。
                          • 日志排查:
                            log.info("Received: page={}, size={}", pageWithSearch.getPage(), pageWithSearch.getPageSize());
                            

                            🎬 尾声

                            从 500 错误的迷雾到揭开字段名不一致的真相,这场 debug 让我对 JSON 映射有了新认识。希望这篇博客能帮你在前后端对接时少踩坑!有问题欢迎留言,咱们一起聊技术!✌️

                            前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” !!!

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码