高级双向杰克逊序列化以避免无限递归
Posted
技术标签:
【中文标题】高级双向杰克逊序列化以避免无限递归【英文标题】:Advanced bidirection jackson serialization to avoid infinite recusion 【发布时间】:2021-03-10 03:01:19 【问题描述】:我有一个 Spring Data 项目,它大致有实体设置,我在下面的最小实现中展示了我的问题:
public class JacksonTest
@Test
public void userWithRoles() throws JsonProcessingException
User u1 = new User();
u1.setName("U1");
Role r1 = new Role();
r1.setName("R1");
UserRole ur1 = new UserRole();
ur1.setRole(r1);
ur1.setUser(u1);
ur1.setMetaData("metaData1");
u1.setRoles(Collections.singletonList(ur1));
r1.setUsers(Collections.singletonList(ur1));
String result = new ObjectMapper().writeValueAsString(u1);
/*
Expected result
name: U1,
roles: [metaData: metaData1, role: name: R1]
*/
@Test
public void roleWithUsers() throws JsonProcessingException
User u1 = new User();
u1.setName("U1");
Role r1 = new Role();
r1.setName("R1");
UserRole ur1 = new UserRole();
ur1.setRole(r1);
ur1.setUser(u1);
ur1.setMetaData("metaData1");
u1.setRoles(Collections.singletonList(ur1));
r1.setUsers(Collections.singletonList(ur1));
String result = new ObjectMapper().writeValueAsString(r1);
/*
Expected result
name: R1,
users: [metaData: metaData1, user: name: U1]
*/
@Data
class UserRole
User user;
Role role;
String metaData;
@Data
class User
String name;
List<UserRole> roles;
@Data
class Role
String name;
List<UserRole> users;
运行任何一个测试都会导致无限递归。
我曾尝试使用@JsonIgnore
、@JsonManagedReference
、@JsonBackReference
来解决我的问题,但它们都不能使两个测试都变成绿色。
我遇到的主要问题是序列化应该给出不同版本的UserRole
,这取决于我是序列化User
还是Role
,如两个测试中所示。
我的问题是如何使这里的两个测试都与预期的输出一起工作?
【问题讨论】:
在这两种情况下,您都在序列化用户,那么为什么要区分呢? 我的错,我已经更新了这个例子。问题是一样的 【参考方案1】:写一个自定义JsonSerializer
List<UserRole> roles
中的User
@see UserUserRoleSerializer
和另一个List<UserRole> users
in Role
@see RoleUserRoleSerializer
@Data
class UserRole
User user;
Role role;
String metaData;
@Data
class User
String name;
@JsonSerialize(using = UserUserRoleSerializer.class)
List<UserRole> roles;
@Data
class Role
String name;
@JsonSerialize(using = RoleUserRoleSerializer.class)
List<UserRole> users;
class RoleUserRoleSerializer extends JsonSerializer<List<UserRole>>
@Override
public void serialize(List<UserRole> value, JsonGenerator gen, SerializerProvider provider) throws IOException
gen.writeStartArray();
for (UserRole userRole : value)
gen.writeStartObject();
gen.writeObjectField("role", userRole.role.name);
gen.writeObjectField("metadata", userRole.metaData);
gen.writeEndObject();
gen.writeEndArray();
class UserUserRoleSerializer extends JsonSerializer<List<UserRole>>
@Override
public void serialize(List<UserRole> value, JsonGenerator gen, SerializerProvider provider) throws IOException
gen.writeStartArray();
for (UserRole userRole : value)
gen.writeStartObject();
gen.writeObjectField("user", userRole.user.name);
gen.writeObjectField("metadata", userRole.metaData);
gen.writeEndObject();
gen.writeEndArray();
这将输出:
userWithRoles:"name":"U1","roles":["user":"U1","metadata":"metaData1"]
roleWithUsers:"name":"R1","users":["role":"R1","metadata":"metaData1"]
【讨论】:
以上是关于高级双向杰克逊序列化以避免无限递归的主要内容,如果未能解决你的问题,请参考以下文章