I have a controller handling a route like 'POST /doit', the json body is automatically parsed into a case class using Finatra built in tools (Jackson, etc), something like this:
class MyController extends Controller {
post("/doit") { request: MyRequest =>
// something
}
}
case class MyRequest(
id: String,
custom: String
)
Here are some valid requests:
{ "id": "my id", "custom": "my custom" }
{ "id": "my id", "custom": "{'x': 'y'}" }
As you can see, 'custom' field can be a JSON which can't be deserialized because Jackson expect it to be a POJO instead of a String, I tried wrapping this JSON with quotes but they are ignored and the field is handled as JSON.
How can I let Jackson library to know that this field should be kept plain?
I had read and the best solution I came up with is to write a custom deserializer, in this case, I have not idea how to integrate with Finatra.
As "Ryan O'Neill" pointed out in Finatra Google Group, there are examples for writing a custom deserializer in ExampleCaseClasses.scala.
I'm copying the following code from previous scala source:
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)
}
Thanks Ryan.