ObjectMapper.readerForUpdating嵌套对象更新失效问题求助
解决Jackson readerForUpdating结合JsonView更新嵌套列表的问题
问题核心
使用readerForUpdating结合JsonView做权限控制时,主实体A的属性更新符合预期,但嵌套的B对象列表出现异常:
- 无
@JsonMerge注解时:列表被完全替换,新建的B对象中无权限字段(如name)会被设为null - 添加
@JsonMerge注解后:新旧B对象共存,旧对象的有权限字段(如property)不更新,新对象的无权限字段为null
根本原因
Jackson默认处理列表时,要么直接替换整个集合,要么(加@JsonMerge后)追加新元素,无法自动匹配现有列表中的对象并合并属性——因为没有标识字段让Jackson识别哪些是同一个对象,同时JsonView仅控制字段是否被反序列化,不处理对象匹配逻辑。
解决方案
1. 给嵌套对象B添加唯一标识字段
给B类增加一个所有权限都能访问的唯一标识(比如id),让Jackson能定位到要更新的现有对象:
public class B { // 所有权限都能读取,用于匹配现有对象 @JsonView({WritePermission.Admin, WritePermission.User}) private Long id; @JsonView(WritePermission.Admin) private String name; @JsonView(WritePermission.User) private String property; // getter、setter省略 }
2. 配置列表字段的合并规则
给A类的list字段添加@JsonMerge,启用列表元素的合并逻辑:
public class A { @JsonView(WritePermission.Admin) private String name; @JsonView(WritePermission.User) private String property; @JsonView(WritePermission.User) @JsonMerge // 启用列表元素合并 private List<B> list; // getter、setter省略 }
3. 配置ObjectMapper启用对象标识匹配
给B类添加@JsonIdentityInfo注解,指定用id字段作为唯一标识,让Jackson能识别同一个对象:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class B { // ... 其余代码不变 }
4. 验证反序列化逻辑
保持原有的反序列化代码即可:
A updatedEntity = objectMapper.readerForUpdating(initialEntityOfAClass) .withView(WritePermission.User.class) .forType(A.class) .readValue(json);
效果说明
- 当JSON中的B对象包含
id时,Jackson会找到初始列表中对应id的B对象,仅更新User权限允许的property字段,保留原有的name值 - 若JSON中的B对象无匹配
id,会作为新元素追加到列表中(符合@JsonMerge的行为) - 无权限的字段(如B的
name)不会被覆盖,始终保留初始值
内容的提问来源于stack exchange,提问作者Eni
相关产品推荐
相关产品推荐

