Jakarta ee JAX-RS-如何获得资源的多个表示/投影?

Jakarta ee JAX-RS-如何获得资源的多个表示/投影?,jakarta-ee,jaxb,jax-rs,projection,jaxb2,Jakarta Ee,Jaxb,Jax Rs,Projection,Jaxb2,情景: 这是一个使用普通JavaEE7的RESTAPI 这里有一个人实体 GET/persons返回所有人员的列表 GET/persons/{id}返回一个人 现在,我希望这些API端点返回实体的不同表示形式: /人员应仅返回id、姓氏和姓氏 /persons/{id}应返回所有字段 我已经想到了: DTO方法:创建一个PersonSummary类,只包含id、firstName和lastName字段。然后使用推土机或其他绘图工具从Person->PersonSummary复制字段。然后返回Pe

情景:

这是一个使用普通JavaEE7的RESTAPI 这里有一个人实体 GET/persons返回所有人员的列表 GET/persons/{id}返回一个人 现在,我希望这些API端点返回实体的不同表示形式:

/人员应仅返回id、姓氏和姓氏 /persons/{id}应返回所有字段 我已经想到了:

DTO方法:创建一个PersonSummary类,只包含id、firstName和lastName字段。然后使用推土机或其他绘图工具从Person->PersonSummary复制字段。然后返回PersonSummary对象列表

使用javax.json.json:手动组装要返回的对象。但这样我只得到JSON,没有更多的XML:

XML模式文件:不知道这是否真的可以为每个表示编写一个.xsd文件,并让Jaxb处理结果表示

到目前为止我所看到的:

在Spring中,您可以简单地创建一个包含所有getter的接口,这应该包括在内。就像这里的底部

对于Jackson,您可以使用@JsonView来实现这一点

使用MOXy有@XmlNamedObjectGraphs

有没有一种简单的方法可以用JavaEE实现这一点?或者有什么好的外部图书馆吗

编辑:运行时注释操作 你对这个想法怎么看这基本上就像Jackson的@JsonView:

@XmlRootElement
public class MyClass {
  @MyViewAnnotation @MyOtherViewAnnotation
  String s1;

  String s2;

  @MyViewAnnotation
  String s3;
}
那怎么办?伪码

// resource object comes from some JAX-RS interceptor along
// with the preferred view annotation (in this case @MyViewAnnotation)

Annotation viewAnnotation = @MyViewAnnotation;

for(Field f : resource) {
  if(f.hasAnnotation(viewAnnotation)) {
    f.addAnnotation(@XmlElement);
  } else {
    f.addAnnotation(@XmlTransient);
  }
}

// return manipulated resource object back to JAX-RS
预期成果:

当传递@MyViewAnnotation时,它将生成@XmlElement字符串s1和@XmlElement字符串s2。s3将是@XmlTransient

当传递@MyOtherViewAnnotation时,它将在s1上生成@XmlElement。s2和s3将是@XmlTransient

我不知道是否有可能在正确的位置拦截JAX-RS处理,以创建一个修改过的类,然后将该类传递给正常的JAX-RS处理。但这样做很容易,JAX-RS可以以同样的方式生成JSON和XML


有什么想法吗?

在JAX-RS中,我唯一能想到的支持此行为的方法是使用具有特殊内容类型的自定义MessageBodyWriter,例如application/json+列表与application/json+详细信息。然后在MessageBodyWriter中,仅序列化那些特定字段

假设您使用jacksonjax-RS提供程序,那么jacksonviews方法似乎最适合您的需要。您还可以使用@JsonSerializeinclude=NON_NULL,并在列表视图中将其他字段设置为NULL,从而得到相同的结果。然而,这仍然是一个特定于杰克逊的解决方案


我注意到,对于其他两个解决方案,您使用了以数据库为中心的方法。我假设这个对象实际上不在您的数据库中。

谢谢您的回答。但我认为MessageBodyWriter不太合适:我必须为每种内容类型编写n个实现或切换大小写,一个用于JSON,一个用于XML,等等。如果我错了,请纠正我。。。几分钟前,我想到了另一个疯狂的想法:如何通过反射进行注释操作?几分钟后,我会在我的问题后面附上一个例子。