我在如何将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。
我也用球衣做了一些测试,但也遇到了同样的问题
答案 0 :(得分:3)
由于没有人知道作者字段和URI之间的关系,因此不能自动发生。使用插件reasteasy-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;
}
Serializer看起来像这样:
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。