使用Jackson和Spring将JavaScript数组反序列化为Java LinkedHashSet不会删除重复项

Mic*_*dis 10 java spring json jackson

假设我有这个客户端JSON输入:

{
   id: "5",
   types: [
      {id: "1", types:[]},
      {id: "2", types:[]},
      {id: "1", types[]}
   ]
}
Run Code Online (Sandbox Code Playgroud)

我有这门课:

class Entity {
    private String id;
    private Set<Entity> types = new LinkedHashSet<>();

    public String getId() {
        return this.id;
    }

    public String setId(String id) {
        this.id = id;
    }

    public Set<Entity> getTypes() {
        return types;
    }

    @JsonDeserialize(as=LinkedHashSet.class)
    public void setTypes(Set<Entity> types) {
        this.types = types;
    }

    @Override
    public boolean equals(Object o){
        if (o == null || !(o instanceof Entity)){
            return false;
        }
        return this.getId().equals(((Entity)o).getId());
    }
}
Run Code Online (Sandbox Code Playgroud)

我有这个Java Spring端点,我在POST请求的主体中传递输入:

@RequestMapping(value = "api/entity", method = RequestMethod.POST)
public Entity createEntity(@RequestBody final Entity in) {
    Set<Entity> types = in.getTypes();
    [...]
}
Run Code Online (Sandbox Code Playgroud)

我想:

Set<Entity> types = in.getTypes();

只有两个条目的顺序正确...因为其中一个是基于id的重复...而是我在LinkedHashSet(!)中得到重复

我从代码中想到,删除重复项会自动运行,但显然不是.

这个问题有一个比我为什么需要覆盖Java中的equals和hashCode方法更广泛的上下文 因为它是通过Java Spring使用隐式的Jackson序列化.

Gur*_*ngh 6

只有重写equals方法才能起作用,因为基于散列的集合同时使用equalshashCode方法来查看两个对象是否相同.你需要重写hashCode()的方法Entity类既hashCode()equals()方法需要被正确执行基于散列的集合工作.

如果你的要求是如果Entity类的两个对象的部分或全部字段相同,那么这两个对象被认为是等价的,在这种情况下,你必须覆盖both equals()hashCode()method.

例如 - 如果只id需要Entity类中的字段来确定两个对象是否相等,那么你将覆盖equals(),如下所示:

@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o instanceof Entity){
        Entity that = (Entity) o;
        return this.id == null ? that.id == null : this.id.equals(that.id);
    }
    return false;

}
Run Code Online (Sandbox Code Playgroud)

但是与它一起,hashCode()如果id具有相同的值,则需要以一种方式重写该方法以生成相同的哈希码,可能是这样的:

@Override
public int hashCode() {
    int h = 17;
    h = h * 31 + id == null ? 0 : id.hashCode();
    return h;
}
Run Code Online (Sandbox Code Playgroud)

只有现在它才能与基于Hash的集合一起正常工作,因为这两种方法都用于唯一地标识对象.


更多关于此: