Jakarta EE 10序列化Person实体触发递归检查异常求助
解决Jakarta EE 10(WildFly 31)下JSON序列化递归引用异常问题
问题根源
WildFly 31默认使用Eclipse Yasson作为Jakarta JSON-B的实现,而Java EE 8通常采用MOXy(JAXB实现)处理JSON序列化。你在角色实体上标注的@XmlTransient是JAXB注解,Yasson并不会优先识别它,因此双向关联的递归引用依然会触发序列化异常。
解决方案
针对Yasson的特性,用JSON-B原生注解替代或补充JAXB注解,即可解决递归问题:
方案1:使用@JsonbTransient忽略反向关联
直接在角色实体的person属性上替换@XmlTransient为JSON-B的@JsonbTransient注解,标记该属性不参与序列化:
public class Player { @OneToOne(mappedBy = "player") @JsonbTransient // 替换原@XmlTransient private Person person; // 其他字段、getter/setter } // Coach、Referee类做同样修改
方案2:用@JsonbManagedReference + @JsonbBackReference处理双向关联
如果需要保留双向关联的序列化逻辑(仅避免递归),可以用这对注解明确关联方向:
- 在Person实体的角色关联字段上标注
@JsonbManagedReference(主动序列化端):
public class Person { @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "player_id") @JsonbManagedReference private Player player; @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "coach_id") @JsonbManagedReference private Coach coach; @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "referee_id") @JsonbManagedReference private Referee referee; // 其他字段、getter/setter }
- 在角色实体的
person属性上标注@JsonbBackReference(被动忽略端):
public class Player { @OneToOne(mappedBy = "player") @JsonbBackReference private Person person; // 其他字段、getter/setter } // Coach、Referee类做同样修改
方案3:配置Yasson忽略未初始化的延迟加载对象
如果关联使用了FetchType.LAZY,Yasson序列化时可能触发代理对象加载导致递归,可以通过JSON-B配置忽略未初始化的属性:
创建JsonbConfig实例并设置序列化规则,在REST端点中使用:
@Provider public class JsonbConfigProvider implements ContextResolver<Jsonb> { @Override public Jsonb getContext(Class<?> type) { JsonbConfig config = new JsonbConfig() .withSerializationInclusion(JsonbSerializationInclusion.NON_EMPTY) .withPropertyVisibilityStrategy(new PropertyVisibilityStrategy() { @Override public boolean isVisible(Field field) { return true; } @Override public boolean isVisible(Method method) { return true; } }); return JsonbBuilder.create(config); } }
验证
修改后重新部署服务,序列化Person列表时会自动跳过角色实体中指向Person的反向引用,避免递归异常,同时保留Person的角色信息正常输出。
内容的提问来源于stack exchange,提问作者Kawu
相关产品推荐
相关产品推荐

