假设我收到一些如下所示的 JSON:
{
"class": "TimesContainer",
"times": ["08:00", "09:15", "12:30"]
}
可能还有其他一些领域,但我正在简化这个问题。我想将此 JSON 反序列化为以下类的对象:
class TimesContainer(
@JsonProperty("times")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm")
@JsonDeserialize(using = LocalTimeListDeserializer::class)
val timesOfDay: List<LocalTime>
) {
//Other code here
}
我的要求是使用 LocalTime 的自然顺序对 timesOfDay 列表进行排序,并且列表不为空。
到目前为止,我有一个自定义反序列化器,专门用于 LocalTime 列表:
class LocalTimeListDeserializer(private val formatter: DateTimeFormatter? = null)
: StdDeserializer<List<LocalTime>>(List::class.java), ContextualDeserializer {
@Throws(JsonMappingException::class)
override fun createContextual(context: DeserializationContext, property: BeanProperty): JsonDeserializer<*> {
val format: JsonFormat.Value? = findFormatOverrides(context, property, handledType())
if (format != null) {
if (format.hasPattern()) {
val pattern = format.pattern
return LocalTimeListDeserializer(DateTimeFormatter.ofPattern(pattern))
}
}
return this
}
override fun deserialize(parser: JsonParser, context: DeserializationContext): List<LocalTime>? {
val formatter = this.formatter ?: DateTimeFormatter.ISO_LOCAL_TIME
if (parser.currentTokenId == JsonTokenId.ID_START_ARRAY) {
val list: MutableList<LocalTime> = mutableListOf()
while (parser.nextToken() != JsonToken.END_ARRAY) {
if (parser.currentToken == JsonToken.VALUE_STRING) {
try {
list.add(LocalTime.parse(parser.valueAsString, formatter))
} catch (dtpe: DateTimeParseException) {
throw context.weirdStringException(parser.valueAsString, LocalTime::class.java, dtpe.message).initCause(dtpe)
}
} else {
throw context.wrongTokenException(parser, LocalTime::class.java, JsonToken.VALUE_STRING, "Invalid time of day")
}
}
if (list.isEmpty()) {
throw context.reportInputMismatch(List::class.java, "TimesContainer requires at least one time of day")
}
return list.sorted()
} else {
throw context.wrongTokenException(parser, List::class.java, JsonToken.START_ARRAY, "Invalid list of times of day")
}
}
}
我正在寻找一种更简单的方法来强制列表非空。我可以在 TimesContainer 的构造函数中对列表进行排序。
在之前的尝试中,我在 TimesContainer 的构造函数中引发了异常,但是这导致了 InvalidDefinitionException,这意味着类定义有问题。因此,我认为这不是正确的方法,因为类定义是正确的。
我还考虑在反序列化后单独验证列表,但我意识到这意味着我不再利用 Jackson 来准确地通知用户他们的 JSON 哪里出错了。
到目前为止,我正在使用以下库:
- com.fasterxml.jackson.module:jackson-module-kotlin:2.9.+
- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.+
我检查了https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations和https://github.com/FasterXML/jackson-databind/wiki/Databind-Annotations以尝试找到可能的注释帮助解决这个问题,但我很难过。