次のような 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 が発生しました。これは、クラス定義に何か問題があることを意味します。したがって、クラス定義が正しいため、これは正しい方法ではないと思います。
また、デシリアライズ後にリストを個別に検証することも検討しましたが、JSON のどこが間違っているかをユーザーに正確に知らせるために Jackson を利用しなくなったことを意味することに気付きました。
これまでのところ、次のライブラリを使用しています。
- 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を調べて、これを助けますが、私は困惑しています。