关于 java:jackson 反序列化与 2 个字段自引用同一个类(自引用循环)

jackson deserialization with 2 fields self referencing the same class (self-reference cycle)

我有下面的类引用自身:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Entity
@Inheritance(strategy = TABLE_PER_CLASS)
//@JsonIdentityInfo(property="rowId", generator = ObjectIdGenerators.PropertyGenerator.class)
public abstract class AbstractEntity implements Serializable {
    /**
     *
     */

    private static final long serialVersionUID = 568799551343430329L;

    @OneToOne(optional=false, fetch=FetchType.EAGER)
    @JoinColumn(name="createdBy")
    protected User createdBy;
    @OneToOne(optional=false, fetch=FetchType.EAGER)
    @JoinColumn(name="lastUpdatedBy")
    protected User lastUpdatedBy;

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(unique = true, nullable = false, updatable = false, length = 7)
    private Integer rowId;

    public User getCreatedBy() {
        return this.createdBy;
    }

    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    public User getLastUpdatedBy() {
        return this.lastUpdatedBy;
    }

    public void setLastUpdatedBy(User lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    public Integer getRowId() {
        return this.rowId;
    }

    public void setRowId(Integer RowId) {
        this.rowId = RowId;
    }

    public String toString() {
        return"[Id]:" + this.rowId +" - [CreatedBy]:" + this.createdBy;
    }
}

然后我有一个类 User 扩展这个类和一个 RepositoryUser 接口:

1
2
3
public interface RepositoryUser extends CrudRepository<User, Integer> {

}

还有一个控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Controller
@RequestMapping(path ="/user")
public class ServiceUser {
    @Autowired
    private RepositoryUser repositoryUser;

    @GetMapping(path="/all", produces ="application/json; charset=UTF-8", headers ="Accept=application/json")
    public @ResponseBody Iterable<User> getAllUsers() {
        return repositoryUser.findAll();
    }

    @PostMapping(path="/add", consumes="application/json")
    public @ResponseBody User createOneUser(@RequestBody User user) {
        System.out.println(user);
        return repositoryUser.save(user);
    }
}

我的问题是我在同一个类中两次引用用户(createdby 和 lastupdatedby),或者我尝试了 JSonIdentityInfo、Jsonmanaged、jsonback 没有任何效果。正确。

我需要能够拥有
{
用户 1 数据,包括创建者和上次更新者
用户 2 数据,包括创建者和上次更新者
}

当我添加时,我需要设置创建记录的用户。

你能帮帮我吗?

非常感谢!


您可以使用 StdSerializer 编写/尝试自定义序列化程序。

CustomJsonSerializer 示例。注意:没有运行代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CustomJsonSerializer extends StdSerializer<AbstractEntity> {

  public CustomJsonSerializer() {
    this(null);
  }

  public CustomJsonSerializer(Class<AbstractEntity> t) {
    super(t);
  }

  @Override
  public void serialize(AbstractEntity value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
    Field[] fields = value.getClass().getDeclaredFields();
    jgen.writeStartObject();

    for (Field field : fields) {
        field.setAccessible(true);

       try {
           // Do the proper field mapping for field types . Object type example
           jgen.writeObjectField(field.getName(), field.get(value));

        } catch (Exception e) {
          // catch error
        }
    }

    jgen.writeEndObject();
  }
}

然后在你的 Rest Method 上使用 @JsonSerialize

1
2
3
4
5
@JsonSerialize(using = CustomJsonSerializer.class)
@GetMapping(path="/all", produces ="application/json; charset=UTF-8", headers ="Accept=application/json")
public @ResponseBody Iterable<User> getAllUsers() {
    return repositoryUser.findAll();
}

请参阅自定义序列化器和标准序列化器

可能的不同解决方案
杰克逊双向无限递归