【问题标题】:Provide link instead of serializing collection提供链接而不是序列化集合
【发布时间】:2016-05-27 22:02:09
【问题描述】:

我有两个班级:

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 boot 应用程序,我想返回 A。

问题是 A 包含一个Set&lt;B&gt;,所以我得到了一个无限嵌套级别的问题。

我找到了一个解决方案:提供一个链接而不是资源本身,这样我就可以拥有这个:

{ "property" : "value", "bs" : "http://mywebsite/api/a/2/bs" }

而且我没有遇到任何嵌套级别问题,因为每个级别都是单独序列化的。

如何在我的 JAX-RS 应用程序中实现这样的事情?我一无所获,但我知道这是可能的,因为Spring Data Neo4j REST 正在使用它,而且效果很好。

【问题讨论】:

  • 停止使用 jax-rs - 如果没有大量工作,它就无法做到这一点。开始使用弹簧数据休息代替。这类事情没有标准,但 spring 选择了当前有用的特定实现。
  • @EngineerDollery 问题是 Spring Data Rest 给了我这个问题:stackoverflow.com/questions/35412463/…
  • 检查this out
  • @peeskillet 你的例​​子很好,但它不允许我提供链接而不是项目集合。我想我正在寻找一些 hal+json。

标签: java spring rest jackson jax-rs


【解决方案1】:

我可以想到以下可能的方法来实现这一目标。

在序列化期间使用 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;
}

并像这样设置 URL:

@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();

【讨论】:

猜你喜欢
  • 2018-03-23
  • 2018-09-19
  • 2012-05-23
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 2016-05-15
  • 1970-01-01
相关资源
最近更新 更多