(де) сериализация свойств делегата kotlin с помощью jackson
Как я могу (де) сериализовать свойства делегата kotlin с помощью jackson. У меня есть такой класс
class MyClass {
var a: Int = 42
set(value) {
val changed = field != value
field = value
if (changed) notifyListeners()
}
... and a dozen other properties that all follow this pattern ...
}
Я хотел упростить это, используя
class MyClass {
var a: Int by NotifyUiOnChange(42)
...
private inner class NotifyUiOnChange<T>(initialValue: T) : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
notifyUiListeners()
}
}
}
но тогда Джексон проигнорирует это свойство.
Как я могу сказать Джексону сериализовать и десериализовать это свойство? И как мне тогда применить аннотации @JsonIgnore (или что-то подобное)?
1 ответ
Вы должны использовать устаревшую версию для Jackson (или, может быть, версию для Java, а не Kotlin?). Я проверил это с помощью"com.fasterxml.jackson.module:jackson-module-kotlin:2.10.+"
(решено в 2.10.1).
Я объявил два класса:
class MyClass {
var a: Int = 42
set(value) {
val changed = field != value
field = value
if (changed) notifyListener(field)
}
private fun notifyListener(field: Any?) {
println("changed: $field")
}
}
class MyDelegatedClass {
var a: Int by NotifyUi(42)
private inner class NotifyUi<T>(initialValue: T) : ObservableProperty<T>(initialValue) {
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
notifyListener(newValue)
}
}
private fun notifyListener(field: Any?) {
println("changed: $field")
}
}
Моя основная функция:
fun main() {
val noDelegate = MyClass()
val delegated = MyDelegatedClass()
val mapper = ObjectMapper().registerKotlinModule()
// Deserialization
val noDelegateValue = mapper.writeValueAsString(noDelegate)
val delegatedValue = mapper.writeValueAsString(delegated)
println("No delegate:\t$noDelegateValue")
println("With delegate\t$delegatedValue")
// Serialization
val noDelegateObject = mapper.readValue<MyClass>("{\"a\":42}".trimIndent())
val delegateObject = mapper.readValue<MyDelegatedClass>("{\"a\":42}".trimIndent())
}
Выход:
No delegate: {"a":42}
With delegate {"a":42}
changed: 42
Мы даже можем видеть вывод делегата, когда используем свойство делегата:) (я считаю, что это побочный эффект, который на самом деле следует рассматривать как ошибку)
Итак, обработка делегатов - это нестандартная функция в Джексоне (я не уверен, с каких пор, но я использовал lazy
делегировать с jackson
в старом проекте я участвовал, и с делегатами проблем не было).
Как игнорировать делегированное свойство?
Итак, вы не можете подать заявку JsonIgnore
аннотацию к делегированному полю, потому что вы получите This annotation is not applicable to target 'member property with delegate'
. Но вы можете определить область применения аннотации. Пример ниже:
class MyDelegateClass {
@get:JsonIgnore // or set:
val a: Int by NotifyUi(42)
}
К сожалению, кажется, что он сломан, потому что вы можете использовать get:
или set:
и это относится не только к геттеру или сеттеру, но и к обоим.