akka http 使用 Json 支持和 xmlsupport
akka http to use Json Support and xmlsupport
我想在部门为 "hr" 时以 xml 格式打印数据,但在部门为 "tech" 时以 json 格式打印数据。
我们可以使用
喷-json一起支持https://doc.akka.io/docs/akka-http/current/common/json-support.html and XML support https://doc.akka.io/docs/akka-http/current/common/xml-support.html
private[rest] def route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri =>
complete {
flag match {
case "hr": => {
HttpEntity(MediaTypes.`application/xml`.withCharset(HttpCharsets.`UTF-8`),"hr department")
}
case "tech" =>{
HttpEntity(ContentType(MediaTypes.`application/json`), mapper.writeValueAsString("tech department"))
}
}
}
}
}
}
}
我试过的解决方法
我通过使用 JsonProtocols 和 ScalaXmlSupport 尝试了以下内容,我得到了预期的 ToResponseMarshallable 编译错误,但找到了 Department
case class department(name:String)
private[rest] def route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri =>
complete {
flag match {
case "hr": => {
complete(department(name =flag))
}
case "tech" =>{
complete(department(name =flag))
}
}
}
}
}
}
}
我认为你必须克服几个问题才能实现你想要的:
您想根据请求参数自定义响应类型。这意味着基于 implicit
的标准封送处理对您不起作用,您必须执行一些明确的步骤
您想将一些业务对象编组到 XML 字符串中。不幸的是,ScalaXmlSupport
that you referenced does not support this, it can marshal only an XML-tree into a response. So you'll need some library that can do XML serialization. One option would be to use jackson-dataformat-xml with jackson-module-scala。这也意味着您必须编写自己的自定义 Marshaller
。还好没那么难
下面是一些可能适合您的简单代码:
import akka.http.scaladsl.marshalling.{ToResponseMarshallable, Marshaller}
// json marshalling
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import spray.json.DefaultJsonProtocol._
implicit val departmentFormat = DefaultJsonProtocol.jsonFormat1(department)
val departmentJsonMarshaller = SprayJsonSupport.sprayJsonMarshaller[department]
// xml marshalling, need to write a custom Marshaller
// there are several MediaTypes for XML such as `application/xml` and `text/xml`, you'll have to choose the one you need.
val departmentXmlMarshaller = Marshaller.StringMarshaller.wrap(MediaTypes.`application/xml`)((d: department) => {
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new XmlMapper()
mapper.registerModule(DefaultScalaModule)
mapper.writeValueAsString(d)
})
private val route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri => {
flag match {
case "hr" => {
// explicitly use the XML marshaller
complete(ToResponseMarshallable(department(name = flag))(departmentXmlMarshaller))
}
case "tech" => {
// explicitly use the JSON marshaller
complete(ToResponseMarshallable(department(name = flag))(departmentJsonMarshaller))
}
}
}
}
}
}
}
请注意,为了使 Jackson XML 序列化程序正常工作,department
class 应该是顶级 class 否则您将收到有关 bad root 的神秘错误名字.
Akka Http 已经内置了内容类型协商。理想情况下,您应该通过拥有一个知道如何将您的部门变成 xml 或 json 并让客户设置 Accept
header.[=15 的编组器来使用它=]
然而,这听起来可能无法让您的客户这样做,所以您可以这样做,假设您已经为 xml 和 [=20] 制作了 ToEntityMarshaller[department]
=] 使用 ScalaXmlSupport
和 SprayJsonSupport
.
val toXmlEntityMarshaller: ToEntityMarshaller[department] = ???
val toJsonEntityMarshaller: ToEntityMarshaller[department] = ???
implicit val departmentMarshaller = Marshaller.oneOf(toJsonEntityMarshaller, toXmlEntityMarshaller)
def route =
parameters("department") { departmentName =>
// capture the Accept header in case the client did request one
optionalHeaderValueByType[Accept] { maybeAcceptHeader =>
mapRequest ( _
.removeHeader(Accept.name)
// set the Accept header based on the department
.addHeader(maybeAcceptHeader.getOrElse(
Accept(departmentName match {
case "hr" ⇒ MediaTypes.`application/xml`
case "tech" ⇒ MediaTypes.`application/json`
})
))
) (
// none of our logic code is concerned with the response type
complete(department(departmentName))
)
}
}
我想在部门为 "hr" 时以 xml 格式打印数据,但在部门为 "tech" 时以 json 格式打印数据。
我们可以使用 喷-json一起支持https://doc.akka.io/docs/akka-http/current/common/json-support.html and XML support https://doc.akka.io/docs/akka-http/current/common/xml-support.html
private[rest] def route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri =>
complete {
flag match {
case "hr": => {
HttpEntity(MediaTypes.`application/xml`.withCharset(HttpCharsets.`UTF-8`),"hr department")
}
case "tech" =>{
HttpEntity(ContentType(MediaTypes.`application/json`), mapper.writeValueAsString("tech department"))
}
}
}
}
}
}
}
我试过的解决方法 我通过使用 JsonProtocols 和 ScalaXmlSupport 尝试了以下内容,我得到了预期的 ToResponseMarshallable 编译错误,但找到了 Department
case class department(name:String)
private[rest] def route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri =>
complete {
flag match {
case "hr": => {
complete(department(name =flag))
}
case "tech" =>{
complete(department(name =flag))
}
}
}
}
}
}
}
我认为你必须克服几个问题才能实现你想要的:
您想根据请求参数自定义响应类型。这意味着基于
implicit
的标准封送处理对您不起作用,您必须执行一些明确的步骤您想将一些业务对象编组到 XML 字符串中。不幸的是,
ScalaXmlSupport
that you referenced does not support this, it can marshal only an XML-tree into a response. So you'll need some library that can do XML serialization. One option would be to use jackson-dataformat-xml with jackson-module-scala。这也意味着您必须编写自己的自定义Marshaller
。还好没那么难
下面是一些可能适合您的简单代码:
import akka.http.scaladsl.marshalling.{ToResponseMarshallable, Marshaller}
// json marshalling
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import spray.json.DefaultJsonProtocol._
implicit val departmentFormat = DefaultJsonProtocol.jsonFormat1(department)
val departmentJsonMarshaller = SprayJsonSupport.sprayJsonMarshaller[department]
// xml marshalling, need to write a custom Marshaller
// there are several MediaTypes for XML such as `application/xml` and `text/xml`, you'll have to choose the one you need.
val departmentXmlMarshaller = Marshaller.StringMarshaller.wrap(MediaTypes.`application/xml`)((d: department) => {
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
val mapper = new XmlMapper()
mapper.registerModule(DefaultScalaModule)
mapper.writeValueAsString(d)
})
private val route =
(pathPrefix("employee") & get) {
path(Segment) { id =>
parameters('department ? "") { (flag) =>
extractUri { uri => {
flag match {
case "hr" => {
// explicitly use the XML marshaller
complete(ToResponseMarshallable(department(name = flag))(departmentXmlMarshaller))
}
case "tech" => {
// explicitly use the JSON marshaller
complete(ToResponseMarshallable(department(name = flag))(departmentJsonMarshaller))
}
}
}
}
}
}
}
请注意,为了使 Jackson XML 序列化程序正常工作,department
class 应该是顶级 class 否则您将收到有关 bad root 的神秘错误名字.
Akka Http 已经内置了内容类型协商。理想情况下,您应该通过拥有一个知道如何将您的部门变成 xml 或 json 并让客户设置 Accept
header.[=15 的编组器来使用它=]
然而,这听起来可能无法让您的客户这样做,所以您可以这样做,假设您已经为 xml 和 [=20] 制作了 ToEntityMarshaller[department]
=] 使用 ScalaXmlSupport
和 SprayJsonSupport
.
val toXmlEntityMarshaller: ToEntityMarshaller[department] = ???
val toJsonEntityMarshaller: ToEntityMarshaller[department] = ???
implicit val departmentMarshaller = Marshaller.oneOf(toJsonEntityMarshaller, toXmlEntityMarshaller)
def route =
parameters("department") { departmentName =>
// capture the Accept header in case the client did request one
optionalHeaderValueByType[Accept] { maybeAcceptHeader =>
mapRequest ( _
.removeHeader(Accept.name)
// set the Accept header based on the department
.addHeader(maybeAcceptHeader.getOrElse(
Accept(departmentName match {
case "hr" ⇒ MediaTypes.`application/xml`
case "tech" ⇒ MediaTypes.`application/json`
})
))
) (
// none of our logic code is concerned with the response type
complete(department(departmentName))
)
}
}