【发布时间】:2017-06-28 17:27:00
【问题描述】:
我正在使用 Akka HTTP(Java 版本)来创建 REST API。我有一个返回应用程序/json 的工作概念证明。不幸的是,我找不到任何明确的文档和/或(工作)示例来说明如何使它也返回其他内容(在我的情况下:text/xml)。
这是我目前拥有的相关位(只要我发送没有 Accept 标头或带有 Accept 标头 application/json 的请求,它就会返回 Airport 对象的 JSON 表示):
return route(
get(() ->
pathPrefix("reference", () ->
pathPrefix("v1", () ->
pathPrefix("airport", () ->
parameter("iataCode", (String iataCode) -> {
final CompletionStage<Optional<Airport>> futureMaybeAirport = fetchAirport(iataCode);
return onSuccess(
() -> futureMaybeAirport
, maybeAirport -> maybeAirport.map(airport ->
completeOK(airport, Jackson.marshaller())
).orElseGet(() ->
complete(StatusCodes.NOT_FOUND, "Not Found")
)
);
}
)
)
)
)
)
);
当我将 text/xml 放入 Accept 标头时,我得到一个 HTTP 406。因此,经过一些研究,似乎我必须提供自己的 Marshaller 才能输出 text/xml。知道 Akka 使用 Jackson,我想使用提供 XMLMapper 的 jackson-dataformat-xml 模块。因此,我按如下方式创建了我的自定义 Marshaller(Akka 在他们的 Jackson 课程中也是这样做的):
public static <T> Marshaller<T, RequestEntity> xmlMarshaller() {
return Marshaller.wrapEntity(
u -> toXML(u),
Marshaller.stringToEntity(),
MediaTypes.TEXT_XML
);
}
private static String toXML(Object object) {
try {
return new XmlMapper().writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Cannot marshal to XML: " + object, e);
}
}
到目前为止一切顺利,但现在是棘手的部分:我如何让 Akka HTTP 清楚我现在希望它使用默认的 JSON Marshaller 或这个 XML Marshaller?据我了解,您可以使用 Marshaller.oneOf 来做到这一点。不幸的是,在网上没有找到 oneOf 的一个实际示例(当然也没有在 Akka HTTP 的关于编组的 Java 文档中,它只是 Scala 版本的副本,并注明文档需要修复)。
我想我需要这样做:
List<Marshaller<Airport, RequestEntity>> marshallers = new ArrayList();
marshallers.add(Jackson.marshaller());
marshallers.add(xmlMarshaller());
Marshaller<Airport, RequestEntity> airportMarshaller = Marshaller.oneOf(JavaConversions.asScalaBuffer(marshallers).toSeq());
这样我就可以将我的 completeOk 调整为:
completeOK(airport, airportMarshaller)
不幸的是,我无法让 Marshaller.oneOf 工作,编译器一直在抱怨:
incompatible types: inference variable A has incompatible equality constraints Object,Airport where A,B are type-variables:
A extends Object declared in method <A,B>oneOf(Seq<Marshaller<A,B>>)
B extends Object declared in method <A,B>oneOf(Seq<Marshaller<A,B>>)
鉴于我的 A 和 B(Airport 和 RequestEntity)显然扩展了 Object(Java 中几乎所有东西都是如此),我不清楚究竟是什么问题。因此,如果您有一双新的眼睛,我们将不胜感激!
另外:我在这里假设 Akka HTTP 的内置内容协商将根据 Accept 标头中的值确定使用哪个 Marshaller。我的这个假设是正确的,还是我试图以完全错误的方式解决问题?
【问题讨论】:
标签: java xml marshalling akka-http