in util-jackson/src/main/scala/com/twitter/util/jackson/caseclass/CaseClassDeserializer.scala [519:626]
private[this] def parseConstructorValues(
jsonParser: JsonParser,
context: DeserializationContext,
jsonNode: JsonNode
): (Array[Object], Seq[CaseClassFieldMappingException]) = {
/* Mutable Fields */
var constructorValuesIdx = 0
val constructorValues = new Array[Object](numConstructorArgs)
val errors = mutable.ListBuffer[CaseClassFieldMappingException]()
while (constructorValuesIdx < numConstructorArgs) {
val field = fields(constructorValuesIdx)
try {
val value = field.parse(context, jsonParser.getCodec, jsonNode)
constructorValues(constructorValuesIdx) = value //mutation
} catch {
case e: CaseClassFieldMappingException =>
if (e.path == null) {
// fill in missing path detail
addException(
field,
e.withPropertyPath(CaseClassFieldMappingException.PropertyPath.leaf(field.name)),
constructorValues,
constructorValuesIdx,
errors
)
} else {
addException(
field,
e,
constructorValues,
constructorValuesIdx,
errors
)
}
case e: InvalidFormatException =>
addException(
field,
CaseClassFieldMappingException(
CaseClassFieldMappingException.PropertyPath.leaf(field.name),
CaseClassFieldMappingException.Reason(
s"'${e.getValue.toString}' is not a " +
s"valid ${Types.wrapperType(e.getTargetType).getSimpleName}${validValuesString(e)}",
CaseClassFieldMappingException.JsonProcessingError(e)
)
),
constructorValues,
constructorValuesIdx,
errors
)
case e: MismatchedInputException =>
addException(
field,
CaseClassFieldMappingException(
CaseClassFieldMappingException.PropertyPath.leaf(field.name),
CaseClassFieldMappingException.Reason(
s"'${jsonNode.asText("")}' is not a " +
s"valid ${Types.wrapperType(e.getTargetType).getSimpleName}${validValuesString(e)}",
CaseClassFieldMappingException.JsonProcessingError(e)
)
),
constructorValues,
constructorValuesIdx,
errors
)
case e: CaseClassMappingException =>
constructorValues(constructorValuesIdx) = field.missingValue //mutation
errors ++= e.errors.map(_.scoped(field.name))
case e: JsonProcessingException =>
// don't include source info since it's often blank. Consider adding e.getCause.getMessage
e.clearLocation()
addException(
field,
CaseClassFieldMappingException(
CaseClassFieldMappingException.PropertyPath.leaf(field.name),
CaseClassFieldMappingException.Reason(
e.errorMessage,
CaseClassFieldMappingException.JsonProcessingError(e)
)
),
constructorValues,
constructorValuesIdx,
errors
)
case e: java.util.NoSuchElementException if isScalaEnumerationType(field) =>
// Scala enumeration mapping issue
addException(
field,
CaseClassFieldMappingException(
CaseClassFieldMappingException.PropertyPath.leaf(field.name),
CaseClassFieldMappingException.Reason(e.getMessage)
),
constructorValues,
constructorValuesIdx,
errors
)
case e: InjectableValuesException =>
// we rethrow, to prevent leaking internal injection detail in the "errors" array
throw e
case NonFatal(e) =>
error("Unexpected exception parsing field: " + field, e)
throw e
}
constructorValuesIdx += 1
}
(constructorValues, errors.toSeq)
}