作为scala和akka-http的初学者,我试图加入序列化和编组过程。
该项目使用akka@2.5.2和akka-http@10.0.10“。此外,它还包含akka-http-spray-json
依赖项。
在代码库中,我们使用Java.Util.Currency
(可能会弃用它并不重要,因为我仍然想知道如何添加自定义编组程序。)
鉴于此示例控制器:
def getCurrencyExample: Route = {
path("currencyExample") {
val currency: Currency = Currency.getInstance("EUR")
val code: String = currency.getCurrencyCode
val shouldBeFormated = collection.immutable.HashMap(
"currencyCode" -> code,
"currencyObject" -> currency
)
complete(shouldBeFormated)
}
}
我得到这样的回复,货币对象变空了:
{
currencyObject: { },
currencyCode: "EUR",
}
我期待的是:
{
currencyObject: "EUR",
currencyCode: "EUR",
}
currency
对象应该转换为JSON字符串。由于我不想手动转换每个响应,我想挂钩编组过程并在后台完成。
我想仅为Java.Util.Currency
个对象添加自定义marhaller,但即使reading up on the docs我也不确定如何继续。
描述了多种方法,我不确定哪种方法适合我的需要,或者从哪里开始。
我尝试创建自己的CurrencyJsonProtocol
:
package com.foo.api.marshallers
import java.util.Currency
import spray.json.{DefaultJsonProtocol, JsString, JsValue, RootJsonFormat}
object CurrencyJsonProtocol extends DefaultJsonProtocol {
implicit object CurrencyJsonFormat extends RootJsonFormat[Currency] {
override def read(json: JsValue): Currency = {
Currency.getInstance(json.toString)
}
override def write(obj: Currency): JsValue = {
JsString(obj.getCurrencyCode)
}
}
}
但仅仅存在该文件会破坏我的项目:
[error] RouteDefinitons.scala:90:16: type mismatch;
[error] found : scala.collection.immutable.HashMap[String,java.io.Serializable]
[error] required: akka.http.scaladsl.marshalling.ToResponseMarshallable
[error] complete(shouldBeFormated)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
我不明白为什么。 (由于我的包名称被称为marshaller
,它崩溃了。这完全破坏了项目的编译。
答案 0 :(得分:1)
根据我的理解,你拥有所有的部分,你只需将它们放在一起。
Spray json为编组常用类型提供支持,例如Int,String,Boolean,List,Map等。但是它不知道如何编组'Currency'。并解决您已为“货币”对象创建自定义编组器。你只需要把它插在正确的地方。您需要做的就是将CurrencyJsonProtocol
中的编组器导入到控制器中,如下所示:
import CurrencyJsonProtocol._
同时确保您也拥有以下导入:
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
而喷射json应该会自动选择它。
要了解其工作原理,您需要了解scala中的implicits。虽然当你来自像我这样的java世界时它看起来很神奇,但我可以向你保证它不是。
答案 1 :(得分:0)
你有JsonFormat[Currency]
吗?如果是,请修理它......
如果没有,您应该按照doc并创建:
case class CurrencyResult(currency: Currency, code: String)
trait JsonSupport
:JsonFormat[Currency]
trait JsonSupport
:JsonFormat[CurrencyResult]
作为上述第1点的替代方法,您可以将地图输入为:Map[String, JsValue]
。
答案 2 :(得分:0)
我多年来一直使用Spray支持。也许我应该尝试另一个。无论如何,在Spray中,一种类型的自定义格式化器很简单。 squants.market.currency https://github.com/typelevel/squants
的一个例子import squants.market.{ Currency, Money }
import squants.market._
trait MoneyJsonProtocol extends DefaultJsonProtocol {
implicit object CurJsonFormat extends JsonFormat[Currency] {
def write(currency: Currency): JsValue = JsString(currency.code)
def read(value: JsValue): Currency = value match {
case JsString(currency) =>
defaultCurrencyMap.get(currency) match {
case Some(c) => c
case None => // throw an exception, for example
}
case _ => // throw another exception, for example
}
}
implicit def toJavaBigDecimal(b: math.BigDecimal): java.math.BigDecimal = b.underlying
}