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

news2025/3/26 16:23:37

🚀 前端字段名和后端不一致?解锁 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<InviteCode> inviteCodePage = inviteCodeService.findPaginatedInviteCodeByAdminIdAndSearch(7, pageWithSearch);
    return BaseResult.success(inviteCodePage);
}

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

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

啥?明明传了 pageNumpageSize,怎么炸了?🤔


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

关键代码

服务层:

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

PageWithSearchBasePage

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;
    }
}

初步分析

  • 前端字段pageNumpageSize
  • 后端字段pagesize
  • 问题:字段名不一致,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 流程图:映射失败过程
前端: pageNum=0, pageSize=10
Jackson 映射到 PageWithSearch
page 未匹配, size 未匹配
getPage()=null, getPageSize()=null
PageRequest.of(null, null)
自动拆箱抛 NullPointerException
返回 500: '分页查询失败:null'

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

为什么会这样?

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

解决方案

方案 1:用 @JsonProperty 指定映射

修改 BasePagePageWithSearch

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;
    // ... 其他代码 ...
}
  • 效果
    • 前端用 pageNumpageSizesearchField,后端正确映射。
    • 输入:
      {
        "searchField": "name",
        "pageNum": 0,
        "pageSize": 10
      }
      
      • pageWithSearch.getPage()0
      • pageWithSearch.getPageSize()10
方案 2:全局命名策略

application.yml 中配置:

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

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

public Page<InviteCode> 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);
    }
}
  • 效果
    • pagesizenull 时,用默认值 0 和 10。
Mermaid 流程图:修复过程
前端: pageNum=0, pageSize=10
方案 1: @JsonProperty
page=0, size=10
PageRequest.of(0, 10)
正常返回数据
方案 3: toPageableWithDefault
page=0, size=10

🌈 第五幕:经验与启发

学到了啥?💡

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

小建议 🌟

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

🎬 尾声

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2320922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot的新闻推荐系统(045)

摘要 随着信息互联网购物的飞速发展&#xff0c;国内放开了自媒体的政策&#xff0c;一般企业都开始开发属于自己内容分发平台的网站。本文介绍了新闻推荐系统的开发全过程。通过分析企业对于新闻推荐系统的需求&#xff0c;创建了一个计算机管理新闻推荐系统的方案。文章介绍了…

2024年数维杯数学建模C题天然气水合物资源量评价解题全过程论文及程序

2024年数维杯数学建模 C题 天然气水合物资源量评价 原题再现&#xff1a; 天然气水合物&#xff08;Natural Gas Hydrate/Gas Hydrate&#xff09;即可燃冰&#xff0c;是天然气与水在高压低温条件下形成的类冰状结晶物质&#xff0c;因其外观像冰&#xff0c;遇火即燃&#…

Linux与HTTP中的Cookie和Session

HTTP中的Cookie和Session 本篇介绍 前面几篇已经基本介绍了HTTP协议的大部分内容&#xff0c;但是前面提到了一点「HTTP是无连接、无状态的协议」&#xff0c;那么到底有什么无连接以及什么是无状态。基于这两个问题&#xff0c;随后解释什么是Cookie和Session&#xff0c;以…

linux 备份工具,常用的Linux备份工具及其备份数据的语法

在Linux系统中&#xff0c;备份数据是确保数据安全性和完整性的关键步骤。以下是一些常用的Linux备份工具及其备份数据的语法&#xff1a; 1. tar命令 tar命令是Linux系统中常用的打包和压缩工具&#xff0c;可以将多个文件或目录打包成一个文件&#xff0c;并可以选择添加压…

C++核心语法快速整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要为学过多门语言玩家快速入门C 没有基础的就放弃吧。 全部都是精华&#xff0c;看完能直接上手改别人的项目。 输出内容 std::代表了这里的cout使用的标准库&#xff0c;避免不同库中的相同命名导致混乱 …

使用HAI来打通DeepSeek的任督二脉

一、什么是HAI HAI是一款专注于AI与科学计算领域的云服务产品&#xff0c;旨在为开发者、企业及科研人员提供高效、易用的算力支持与全栈解决方案。主要使用场景为&#xff1a; AI作画&#xff0c;AI对话/写作、AI开发/测试。 二、开通HAI 选择CPU算力 16核32GB&#xff0c;这…

【day2】数据结构刷题 栈

一 有效的括号 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的…

第16章:基于CNN和Transformer对心脏左心室的实验分析及改进策略

目录 1. 项目需求 2. 网络选择 2.1 UNet模块 2.2 TransUnet 2.2.1 SE模块 2.2.2 CBAM 2.3 关键代码 3 对比试验 3.1 unet 3.2 transformerSE 3.3 transformerCBAM 4. 结果分析 5. 推理 6. 下载 1. 项目需求 本文需要做的工作是基于CNN和Transformer的心脏左心室…

云上 Redis 迁移至本地机房

文章目录 摘要在 IDC 搭建读写分离 redis 集群一、环境准备二、部署主从架构1. 安装Redis2. 配置主节点3. 配置从节点4. 所有 Redis 节点设置开机自启动三、部署代理层(读写分离)1. 安装Twemproxy2. 配置Twemproxy3. 配置开机自启动四、高可用配置(哨兵模式)1. 配置哨兵节点…

SQL Server——表数据的插入、修改和删除

目录 一、引言 二、表数据的插入、修改和删除 &#xff08;一&#xff09;方法一&#xff1a;在SSMS控制台上进行操作 1.向表中添加数据 2.对表中的数据进行修改 3.对表中的数据进行删除 &#xff08;二&#xff09;方法二&#xff1a;使用 SQL 代码进行操作 1.向表中添…

deepSeek-SSE流式推送数据

1、背景 DeepSeek作为当前最火的AI大模型&#xff0c; 使用的时候用户在输入框输入问题&#xff0c;大模型进行思考回答你&#xff0c;然后会有一个逐步显示的过程效果&#xff0c;而不是一次性返回整个答案给前端页面进行展示&#xff0c;为了搞清楚其中的原理&#xff0c;我们…

【北京迅为】iTOP-RK3568开发板OpenHarmony系统南向驱动开发UART接口运作机制

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

C#实现自己的Json解析器(LALR(1)+miniDFA)

C#实现自己的Json解析器(LALR(1)miniDFA) Json是一个用处广泛、文法简单的数据格式。本文介绍如何用bitParser&#xff08;拥有自己的解析器&#xff08;C#实现LALR(1)语法解析器和miniDFA词法分析器的生成器&#xff09;迅速实现一个简单高效的Json解析器。 读者可在&#xf…

机器学习——KNN数据均一化

在KNN&#xff08;K-近邻&#xff09;算法中&#xff0c;数据均一化&#xff08;归一化&#xff09;是预处理的关键步骤&#xff0c;用于消除不同特征量纲差异对距离计算的影响。以下是两种常用的归一化操作及其核心要点&#xff1a; 质押 一 、主要思想 1. 最值归一化&#…

异步编程与流水线架构:从理论到高并发

目录 一、异步编程核心机制解析 1.1 同步与异步的本质区别 1.1.1 控制流模型 1.1.2 资源利用对比 1.2 阻塞与非阻塞的技术实现 1.2.1 阻塞I/O模型 1.2.2 非阻塞I/O模型 1.3 异步编程关键技术 1.3.1 事件循环机制 1.3.2 Future/Promise模式 1.3.3 协程&#xff08;Cor…

哈尔滨工业大学DeepSeek公开课人工智能:大模型原理 技术与应用-从GPT到DeepSeek|附视频下载方法

导 读INTRODUCTION 今天继续哈尔滨工业大学车万翔教授带来了一场主题为“DeepSeek 技术前沿与应用”的报告。 本报告深入探讨了大语言模型在自然语言处理&#xff08;NLP&#xff09;领域的核心地位及其发展历程&#xff0c;从基础概念出发&#xff0c;延伸至语言模型在机器翻…

Excel处理控件Spire.XLS系列教程:C# 在 Excel 中添加或删除单元格边框

单元格边框是指在单元格或单元格区域周围添加的线条。它们可用于不同的目的&#xff0c;如分隔工作表中的部分、吸引读者注意重要的单元格或使工作表看起来更美观。本文将介绍如何使用 Spire.XLS for .NET 在 C# 中添加或删除 Excel 单元格边框。 安装 Spire.XLS for .NET E-…

Web开发-JS应用NodeJS原型链污染文件系统Express模块数据库通讯

知识点&#xff1a; 1、安全开发-NodeJS-开发环境&功能实现 2、安全开发-NodeJS-安全漏洞&案例分析 3、安全开发-NodeJS-特有漏洞 node.js就是专门运行javascript的一个应用程序&#xff0c;区别于以往用浏览器解析原生js代码&#xff0c;node.js本身就可以解析执行js代…

国产达梦(DM)数据库的安装(Linux系统)

目录 一、安装前的准备工作 1.1 导包 1.2 创建用户和组 1.3 修改文件打开最大数 1.4 目录规划 1.5 修改目录权限 二、安装DM8 2.1 挂载镜像 2.2 命令行安装 2.3 配置环境变量 2.4 启动图形化界面 三、配置实例 四、注册服务 五、启动 停止 查看状态 六、数据库客…

git的底层原理

git的底层原理 三段话总结git&#xff0c; 1. 工作原理&#xff1a;git管理是一个DAG有向无环图&#xff0c;HEAD指针指向branch或直接指向commit&#xff0c;branch指向commit&#xff0c;commit指向tree&#xff0c;tree指向别的tree或直接指向blob。 2. git所管理的一个目录…