讲师中心 微信公众号
AI工具推荐 视频效率加速

使用Jackson @JsonMerge 实现数据深度合并,避免更新时字段被覆盖

夜静大大_7178

夜静大大_7178

发布时间:2025-11-18 15:36:06

|

304人浏览过

|

来源于php中文网

原创

使用jackson @jsonmerge 实现数据深度合并,避免更新时字段被覆盖

本文深入探讨了在使用Jackson `ObjectReader`进行部分数据更新时,现有嵌套对象字段可能被JSON请求中缺失的字段覆盖为`null`的问题。针对此痛点,教程详细介绍了Jackson 2.9及更高版本引入的`@JsonMerge`注解。通过将此注解应用于需要深度合并的字段,可以有效防止在执行更新操作时,原有数据因JSON请求不完整而被意外擦除,从而实现更智能、更健壮的数据合并策略。

Jackson ObjectReader 部分更新的挑战

在使用Jackson库进行数据更新时,一个常见的场景是从数据库加载一个现有对象,然后使用传入的JSON请求对其进行部分更新。Jackson提供了ObjectReader的readerForUpdating()方法来支持这种操作,旨在将JSON数据合并到现有对象中。然而,在处理包含嵌套对象的模型时,如果不加以特殊处理,可能会遇到一个问题:如果JSON请求中某个嵌套对象的字段缺失,ObjectReader可能会将现有对象中对应的字段值覆盖为null,而不是保留原有的值。

让我们通过一个具体的例子来理解这个问题。假设我们有以下数据模型:

data class Model(
  val fieldTypeA: FieldTypeA? = null,
)

data class FieldTypeA(
  val valueA: String? = null,
  val valueB: String? = null,
)

现在,我们从数据库中加载了一个 Model 实例,其中 fieldTypeA.valueA 已经有值:

val existingModel = Model(fieldTypeA = FieldTypeA(valueA = "Test", valueB = "Existing B"))
// 此时 existingModel.fieldTypeA.valueA = "Test", existingModel.fieldTypeA.valueB = "Existing B"

接下来,我们准备一个用于更新的JSON请求,该请求只包含 fieldTypeA 中的 valueB 字段:

{
  "fieldTypeA": {
    "valueB": "I am value B"
  }
}

我们使用 ObjectReader 进行更新操作:

import com.fasterxml.jackson.databind.ObjectMapper

// 假设 CustomMapper 是一个 ObjectMapper 实例
val objectMapper = ObjectMapper()
val readerForUpdating = objectMapper.readerForUpdating(existingModel)

val jsonRequestString = """{"fieldTypeA":{"valueB":"I am value B"}}"""
val updatedModel: Model = readerForUpdating.readValue(jsonRequestString)

在上述代码执行后,updatedModel 的 fieldTypeA.valueA 将会变成 null,而 fieldTypeA.valueB 则被更新为 "I am value B"。这通常不是我们期望的行为,因为我们希望 valueA 能够被保留。

解决方案:使用 @JsonMerge 实现深度合并

为了解决Jackson ObjectReader 在部分更新时覆盖现有嵌套对象字段的问题,Jackson 2.9 版本引入了一个强大的新特性:@JsonMerge 注解。通过在需要深度合并的字段上标记 @JsonMerge,Jackson将不再简单地用JSON中缺失的值覆盖现有字段,而是尝试进行智能的深度合并。

chartjs-reporter
chartjs-reporter

此技能用于在用户需要将结构化数据(查询结果、CSV 摘要、JSON 记录或 Python 字典/列表)转换为独立的 HTML 页面时使用。

下载

如何使用 @JsonMerge

只需将 @JsonMerge 注解添加到数据模型中需要进行深度合并的字段上。在我们的例子中,我们希望 fieldTypeA 对象在更新时能够深度合并,而不是被完全替换或部分覆盖为 null。因此,我们修改 Model 类如下:

import com.fasterxml.jackson.annotation.JsonMerge

data class Model(
  @JsonMerge // 在 fieldTypeA 字段上添加 @JsonMerge 注解
  val fieldTypeA: FieldTypeA? = null,
)

data class FieldTypeA(
  val valueA: String? = null,
  val valueB: String? = null,
)

@JsonMerge 的工作原理

当Jackson处理一个被 @JsonMerge 注解标记的字段时,它会改变默认的合并行为。具体来说:

  1. 非空检查: 如果现有对象中被注解字段的值不为 null,并且传入的JSON请求中也包含该字段,Jackson会尝试将JSON数据合并到现有字段的实例中,而不是创建一个新的实例。
  2. 保留缺失字段: 如果JSON请求中某个子字段缺失,Jackson将不会将其在现有对象中的对应值设置为 null,而是保留现有对象中该子字段的值。
  3. 递归合并: 如果被注解的字段本身是一个复杂对象,并且其内部的字段也需要深度合并,那么该字段的类定义中也可以继续使用 @JsonMerge。

使用 @JsonMerge 后的示例

让我们再次执行之前的更新操作,但这次 Model 类已经包含了 @JsonMerge 注解:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.annotation.JsonMerge

// 更新后的 Model 定义
data class Model(
  @JsonMerge
  val fieldTypeA: FieldTypeA? = null,
)

data class FieldTypeA(
  val valueA: String? = null,
  val valueB: String? = null,
)

// 现有模型
val existingModel = Model(fieldTypeA = FieldTypeA(valueA = "Test", valueB = "Existing B"))
// 此时 existingModel.fieldTypeA.valueA = "Test", existingModel.fieldTypeA.valueB = "Existing B"

// JSON 请求
val jsonRequestString = """{"fieldTypeA":{"valueB":"I am value B"}}"""

// 执行更新
val objectMapper = ObjectMapper()
val readerForUpdating = objectMapper.readerForUpdating(existingModel)
val updatedModel: Model = readerForUpdating.readValue(jsonRequestString)

// 验证结果
println(updatedModel.fieldTypeA?.valueA) // 输出: Test
println(updatedModel.fieldTypeA?.valueB) // 输出: I am value B

可以看到,updatedModel 中的 fieldTypeA.valueA 成功保留了原有值 "Test",而 fieldTypeA.valueB 也被正确更新为 "I am value B"。这正是我们期望的深度合并行为。

注意事项与总结

  1. Jackson 版本要求: @JsonMerge 注解是在 Jackson 2.9 版本中引入的。如果您的项目使用的是旧版Jackson,则需要升级到 2.9 或更高版本才能使用此功能。
  2. 适用场景: @JsonMerge 特别适用于需要对嵌套对象进行部分更新,并希望保留现有对象中未在JSON请求中提供的字段值的场景。这在RESTful API中处理PATCH请求时非常有用。
  3. 默认行为: 在没有 @JsonMerge 的情况下,Jackson的 readerForUpdating() 对于对象字段的默认行为是替换(如果JSON中存在该字段)或覆盖为 null(如果JSON中该字段存在但其子字段缺失,或者JSON中该字段本身缺失且现有对象中该字段不为 null)。@JsonMerge 改变了这种默认行为,使其更倾向于“合并”而不是“替换”。
  4. 谨慎使用: 并非所有字段都适合使用 @JsonMerge。对于那些你确实希望在JSON中缺失时被清除(设置为 null)的字段,则不应使用此注解。

通过合理利用 @JsonMerge 注解,开发者可以更精确地控制Jackson在执行数据更新时的合并行为,从而构建出更加健壮和用户友好的应用程序,避免因数据意外丢失而引发的问题。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
PHP API接口开发与RESTful实践
PHP API接口开发与RESTful实践

本专题聚焦 PHP在API接口开发中的应用,系统讲解 RESTful 架构设计原则、路由处理、请求参数解析、JSON数据返回、身份验证(Token/JWT)、跨域处理以及接口调试与异常处理。通过实战案例(如用户管理系统、商品信息接口服务),帮助开发者掌握 PHP构建高效、可维护的RESTful API服务能力。

544

2025.11.26

json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2135

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3282

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1096

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

3739

2025.09.10

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1678

2024.03.01

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2745

2023.06.29

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

80

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 21.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn