【问题标题】:RESTEasy POJO json "embedded" objects as links/id'sRESTEasy POJO json“嵌入”对象作为链接/id
【发布时间】:2015-07-23 15:51:41
【问题描述】:

我不知道如何将 POJO 中的嵌入对象表示为链接,而不是直接嵌入它们。

我正在与抛弃提供商一起取消 RESTEasy。全部在 3.0.11.Final 版本中。

Book.java POJO

public class Book
{
    private  Integer bookId;
    private  String title;
    private  Author author;
}

Author.java POJO

public class Author
{
    private  Integer authorId;
    private  String name;
}

当我使用 RESTEasy 生成一本书的 XML 或 JSON 表示时,我看到了:

<book>
    <bookId>1</bookId>
    <title>My book</title>
    <author>
        <authorId>2</authorId>
        <name>Andre Schild</name>
    </author>
</book>

但我不想拥有这个:

<book>
    <bookId>1</bookId>
    <title>My book</title>
    <author author="2"><atom:link rel="list" href="http://.../rest/authors/2"/></author>
</book>

由于我们使用 JPA 进行 db 后端连接,所以 POJO 直接包含作者 POJO,而不仅仅是 ID。

我也用球衣做了一些测试,但也遇到了同样的问题

【问题讨论】:

    标签: java json jpa jax-rs resteasy


    【解决方案1】:

    由于没有人知道作者字段和 URI 之间的关系,这不会自动发生。使用插件 resteasy-links,您可以使用两个注释 @AddLinks@LinkResource 定义这些关系。你可以找到more information in the docs

    此插件不会更改字段的值,但会将原子链接添加到实体。它也仅适用于 Jettison 和 JAXB。

    这是一个使用Jackson 的快速+脏示例,它真正替换了作者字段的值。

    我们将使用这个注解来定义 POJO 和资源之间的关系:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface Linked {
    
        String path();
    
        String rel() default "";
    
    }
    

    这个注解需要应用于Author类:

    @Linked(path = "/rest/authors/{authorId}", rel = "list")
    public class Author {}
    

    在Book字段我们需要添加我们要使用的Serializer:

    public class Book {
        @JsonSerialize(using = LinkedSerializer.class)
        private Author author;
    }
    

    序列化器可能如下所示:

    public class LinkedSerializer extends JsonSerializer<Object> {
    
        @Override
        public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            Linked linked = value.getClass().getAnnotation(Linked.class);
            Matcher matcher = Pattern.compile("\\{(.+?)\\}").matcher(linked.path());
            if (!matcher.find()) {
                return;
            }
            String param = matcher.group(1);
            try {
                Field field = value.getClass().getDeclaredField(param);
                field.setAccessible(true);
                Object paramValue = field.get(value);
                String path = linked.path().replaceFirst("\\{.*\\}", paramValue.toString());
                jgen.writeStartObject();
                jgen.writeFieldName("href");
                jgen.writeString(path);
                jgen.writeFieldName("rel");
                jgen.writeString(linked.rel());
                jgen.writeEndObject();
            } catch (NoSuchFieldException | SecurityException | IllegalAccessException ex) {
                throw new IllegalArgumentException(ex);
            }
        }
    
    }
    

    注意:我们在这里只使用路径而不是完整的 URI,因为我们不知道基本 URI 并且无法在此序列化程序中注入 UriInfo 或 ServletRequest。但是您可以通过ResteasyProviderFactory.getContextData(HttpServletRequest.class) 获取 ServletRequest。

    【讨论】:

    • 刚刚偶然发现了resteasy-links并更新了我的答案。
    猜你喜欢
    • 2013-11-06
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 1970-01-01
    • 2020-03-18
    • 2015-12-14
    • 1970-01-01
    • 2017-05-12
    相关资源
    最近更新 更多