双向多对多关系中的循环引用

tst*_*rms 9 java json many-to-many jackson

我的实体中有多对多的双向关系.请参阅以下示例:

public class Collaboration {

    @JsonManagedReference("COLLABORATION_TAG")
    private Set<Tag> tags;

}

public class Tag {

    @JsonBackReference("COLLABORATION_TAG")
    private Set<Collaboration> collaborations;

}
Run Code Online (Sandbox Code Playgroud)

当我尝试将其序列化为JSON时,我遇到以下异常:`

"java.lang.IllegalArgumentException:无法处理托管/后向引用'COLLABORATION_TAG':后引用类型(java.util.Set)与托管类型(foo.Collaboration)不兼容.

实际上,我知道这是有道理的,因为javadoc明确声明你不能在集合上使用@JsonBackReference.我的问题是,我应该如何解决这个问题?我现在所做的是删除父端的@JsonManagedReference注释,并在子端添加@JsonIgnore.有人能告诉我这种方法有什么副作用吗?还有其他建议吗?

tst*_*rms 4

我最终实施了以下解决方案。

关系的一端被认为是父母。它不需要任何 Jackson 相关的注释。

public class Collaboration {

    private Set<Tag> tags;

}
Run Code Online (Sandbox Code Playgroud)

关系的另一方实现如下。

public class Tag {

    @JsonSerialize(using = SimpleCollaborationSerializer.class)
    private Set<Collaboration> collaborations;

}
Run Code Online (Sandbox Code Playgroud)

我正在使用自定义序列化器来确保不会发生循环引用。序列化器可以这样实现:

public class SimpleCollaborationSerializer extends JsonSerializer<Set<Collaboration>> {

    @Override
    public void serialize(final Set<Collaboration> collaborations, final JsonGenerator generator,
        final SerializerProvider provider) throws IOException, JsonProcessingException {
        final Set<SimpleCollaboration> simpleCollaborations = Sets.newHashSet();
        for (final Collaboration collaboration : collaborations) {
            simpleCollaborations.add(new SimpleCollaboration(collaboration.getId(), collaboration.getName()));                
        }
        generator.writeObject(simpleCollaborations);
    }

    static class SimpleCollaboration {

        private Long id;

        private String name;

        // constructors, getters/setters

    }

}
Run Code Online (Sandbox Code Playgroud)

此序列化程序将仅显示协作实体的一组有限属性。由于省略了“tags”属性,因此不会发生循环引用。

可以在这里找到有关此主题的好读物。它解释了当您遇到类似情况时的所有可能性。