当 Finatra 将请求解析为案例 class 时,我如何设置一个字段以保持原样?

How can I set a field to be kept as plain while Finatra is parsing a request into a case class?

我有一个控制器处理像 'POST /doit' 这样的路由,json 主体使用 Finatra 内置工具(Jackson 等)自动解析为一个案例 class,类似这个:

class MyController extends Controller {
  post("/doit") { request: MyRequest =>
    // something
  }
}

case class MyRequest(
  id: String,
  custom: String
)

以下是一些有效的请求:

{ "id": "my id", "custom": "my custom" }

{ "id": "my id", "custom": "{'x': 'y'}" }

如您所见,'custom' 字段可以是一个 JSON,它不能被反序列化,因为 Jackson 希望它是一个 POJO 而不是字符串,我尝试包装这个 JSON 带引号但它们被忽略并且该字段被处理为 JSON.

我怎样才能让 Jackson 图书馆知道这个字段应该保持简洁?

我读过,我想到的最好的解决方案是编写一个自定义解串器,在这种情况下,我不知道如何与 Finatra 集成。

正如 "Ryan O'Neill" 在 Finatra Google Group, there are examples for writing a custom deserializer in ExampleCaseClasses.scala 中指出的那样。

我正在从以前的 scala 源代码中复制以下代码:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize

case class CaseClassWithCustomDecimalFormat(
  @JsonDeserialize(using = classOf[MyBigDecimalDeserializer])
  myBigDecimal: BigDecimal,
  @JsonDeserialize(using = classOf[MyBigDecimalDeserializer])
optMyBigDecimal: Option[BigDecimal])

class MyBigDecimalDeserializer extends JsonDeserializer[BigDecimal] {
  override def deserialize(jp: JsonParser, ctxt: DeserializationContext): BigDecimal = {
    val jsonNode: ValueNode = jp.getCodec.readTree(jp)
    BigDecimal(jsonNode.asText).setScale(2, RoundingMode.HALF_UP)
  }

  override def getEmptyValue: BigDecimal = BigDecimal(0)
}

谢谢瑞安。