1

假设我收到一些如下所示的 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-Annotationshttps://github.com/FasterXML/jackson-databind/wiki/Databind-Annotations以尝试找到可能的注释帮助解决这个问题,但我很难过。

4

0 回答 0