我有两个班级:
public class A{
private String property;
private Set<B> bs = new HashSet<B>();
}
public class B{
private String property;
private A owner;
}
我创建了一个基本的JAX-RS + Spring启动应用程序,我想返回A.
问题是A包含Set<B>
,因此我得到了无限的嵌套级别问题。
我找到了一个解决方案:提供链接而不是资源本身,这样我就可以拥有:
{ "property" : "value", "bs" : "http://mywebsite/api/a/2/bs" }
我没有得到任何嵌套级别的问题,因为每个级别都是单独序列化的。
如何在JAX-RS应用程序中实现这样的功能?我没有发现任何关于它的信息,但我知道自Spring Data Neo4j REST使用它以来它是可能的,而且效果很好。
答案 0 :(得分:0)
我可以想到以下可能的方法来实现这一目标。
使用XmlAdapter
在序列化期间将集转换为URI@XmlRootElement
public class A
{
private int id;
private String property;
@XmlJavaTypeAdapter(BsAdapter.class)
private Set<B> bs = new HashSet<B>();
}
public class BsAdapter extends XmlAdapter<URI, Set<B>>
{
@Override
public Set<B> unmarshal(URI v) throws Exception
{
return new HashSet<>();
}
@Override
public URI marshal(Set<B> v) throws Exception
{
return URI.create(
Optional.ofNullable(v)
.filter(b -> !b.isEmpty())
.map(b -> "/" + b.stream().findFirst().get().getOwner().getId() + "/bs")
.orElse(""));
}
}
如果A的id是URI的一部分,则只有在该集合不为空时才能检索它。结果是相对URI,因为没有可用的进一步信息。
作为替代方案,手动设置URI。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class A
{
private int id;
private String property;
@XmlTransient
private Set<B> bs = new HashSet<B>();
@XmlElement(name = "bs")
private URI bsUri;
}
并设置如下网址:
@Context
UriInfo uriInfo;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getA()
{
// ...
a.setBsUri(UriBuilder.fromUri(uriInfo.getAbsolutePath())
.path("a")
.path("{id}")
.path("bs")
.build(2));
return Response.ok().entity(a).build();
}
或者,如果HTTP Header中的链接也很好,只需这样做,这样就不必使用URI扩展A类。
return Response.ok().entity(a).link(UriBuilder.fromUri(uriInfo.getAbsolutePath())
.path("a")
.path("{id}")
.path("bs")
.build(2), "bs").build();