in http-core/src/main/scala/com/twitter/finatra/http/marshalling/MessageInjectableValues.scala [250:305]
private[this] def convertWithContext(
context: DeserializationContext,
forProperty: BeanProperty,
javaType: JavaType,
propertyValue: Any
): Object = {
// not a primitive, not a string and starts with a START_OBJECT token
def shouldParseAsObjectType(javaType: JavaType, json: String): Boolean = {
!javaType.isPrimitive && !javaType.hasRawClass(classOf[String]) &&
json.startsWith(JsonToken.START_OBJECT.asString)
}
val jsonNode: JsonNode = propertyValue match {
case json: String if shouldParseAsObjectType(javaType, json) =>
// only parse into a tree node if the incoming java type is not primitive or String type
objectMapper.underlying.readTree(objectMapper.underlying.getFactory.createParser(json))
case _ =>
objectMapper.underlying.valueToTree[JsonNode](propertyValue)
}
val treeTraversingParser = new TreeTraversingParser(jsonNode, objectMapper.underlying)
try {
// advance the parser to the next token for deserialization via deserializer
treeTraversingParser.nextToken
Option(forProperty.getAnnotation(classOf[JsonDeserialize])) match {
case Some(annotation: JsonDeserialize)
if isNotAssignableFrom(annotation.using, classOf[JsonDeserializer.None]) =>
// Jackson doesn't seem to properly find deserializers specified with `@JsonDeserialize`
// unless they are contextual, so we manually lookup and instantiate.
Option(context.deserializerInstance(forProperty.getMember, annotation.using)) match {
case Some(deserializer) =>
deserializer.deserialize(treeTraversingParser, context)
case _ =>
context.handleInstantiationProblem(
javaType.getRawClass,
annotation.using.toString,
JsonMappingException.from(
context,
"Unable to locate/create deserializer specified by: " +
s"${annotation.getClass.getName}(using = ${annotation.using()})")
)
}
case Some(annotation: JsonDeserialize)
if isNotAssignableFrom(annotation.contentAs, classOf[java.lang.Void]) =>
readPropertyValue(
context,
treeTraversingParser,
forProperty,
propertyValue,
Some(annotation.contentAs))
case _ =>
readPropertyValue(context, treeTraversingParser, forProperty, propertyValue, None)
}
} finally {
treeTraversingParser.close()
}
}