구현 띄는 속성을 할 수 있도 직렬화에 틀린

0

질문

나는이 노스의 특정 값은 관찰하지만 또한 직렬화.

이것은 분명히 일어서 직렬화때문에 작동하지만,그것은 매우 상용구-중 하 추가 세터는 모든 단일드와 수동으로 하는 전화 change(...) 내부에는 각 setter:

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }
}

@Serializable
class BlahVO : Observable {

    var value2: String = ""
        set(value) {
            field = value
            change("value2")
        }

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

println(BlahVO().apply { value2 = "test2" }) 제대로 출력

changing value2
{"value2":"test2"}

나는 시도를 소개합 대표단:

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }

    
    @Suppress("ClassName")
    class default<T>(defaultValue: T) {

        private var value: T = defaultValue

        operator fun getValue(observable: Observable, property: KProperty<*>): T {
            return value
        }

        operator fun setValue(observable: Observable, property: KProperty<*>, value: T) {
            this.value = value
            observable.change(property.name)
        }

    }

}

@Serializable
class BlahVO : Observable {

    var value1: String by Observable.default("value1")

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

println(BlahVO().apply { value1 = "test1" }) 올바르게 트리거 변화 감지만,그것은 없는 직렬화:

changing value1
{}

면에서 관찰하 ReadWriteProperty,

interface Observable {

    fun change(message: String) {
        println("changing $message")
    }

    fun <T> look(defaultValue: T): ReadWriteProperty<Observable, T> {
        return OP(defaultValue, this)
    }

    class OP<T>(defaultValue: T, val observable: Observable) : ObservableProperty<T>(defaultValue) {
        override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            super.setValue(thisRef, property, value)
            observable.change("blah!")
        }
    }
}

@Serializable
class BlahVO : Observable {

    var value3: String by this.look("value3")

    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

결과는 동일:

changing blah!
{}

마찬가지로 대부분을 차지했다.vetoable

var value4: String by Delegates.vetoable("value4", {
        property: KProperty<*>, oldstring: String, newString: String ->
    this.change(property.name)
    true
})

출력:

changing value4
{}

대리인에 단지 작동하지 않는 것으로 틀린 Serialization

다른 어떤 옵션이 있습을 관찰하는 숙박 시설의 변경을 파괴하지 않고 직렬화하는 것입니다 또한 다른 플랫폼에서 작동(KotlinJS,KotlinJVM,Android,...)?

1

최고의 응답

2

직렬화를 진행하고의 틀린 대표단에 의해 지원되지 않습 kotlinx.serialization 으로 지금이다.
열린 문제#1578 GitHub 에서 이에 관한 기능입니다.

에 따라 문제를 만들 수 있습니다 중간 데이터 전송 객체를 가져오는 직렬화는 대신 원본 개체입니다. 또한 당신이 쓸 수 있는 사용자 지정 serializer 을 지원하는 직렬화의 틀린 대표하는 것이 더 보일러,다음 사현으로,제안서에서 질문입니다.


데이터 전송 전체

매핑하여 원래의 목적 간단한 데이터 전송을 개체 없이 대리인을 활용할 수 있는 기본 직렬화 메커니즘이 있습니다. 이것은 또한 좋은 부작용을 정화하는 데이터 모델 클래스에서 framework 특정한 주석과 같은 @Serializable.

class DataModel {
    var observedProperty: String by Delegates.observable("initial") { property, before, after ->
        println("""Hey, I changed "${property.name}" from "$before" to "$after"!""")
    }

    fun toJson(): String {
        return Json.encodeToString(serializer(), this.toDto())
    }
}

fun DataModel.toDto() = DataTransferObject(observedProperty)

@Serializable
class DataTransferObject(val observedProperty: String)

fun main() {
    val data = DataModel()
    println(data.toJson())
    data.observedProperty = "changed"
    println(data.toJson())
}

이 수익률은 다음과 같은 결과를 얻을 수 있습니다

{"observedProperty":"initial"}
Hey, I changed "observedProperty" from "initial" to "changed"!
{"observedProperty":"changed"}

사용자 지정 데이터 형식

를 변경하는 경우에 데이터 유형 옵션을 작성할 수 있습니다 포장 클래스에 가져오는(de)직렬화됩니다. 뭔가의 라인을 따라 다음과 같은 작동하지 않을 수 있습니다.

@Serializable
class ClassWithMonitoredString(val monitoredProperty: MonitoredString) {
    fun toJson(): String {
        return Json.encodeToString(serializer(), this)
    }
}

fun main() {
    val monitoredString = obs("obsDefault") { before, after ->
        println("""I changed from "$before" to "$after"!""")
    }
    
    val data = ClassWithMonitoredString(monitoredString)
    println(data.toJson())
    data.monitoredProperty.value = "obsChanged"
    println(data.toJson())
}

는 수익률은 다음과 같은 결과를 얻을 수 있습니다

{"monitoredProperty":"obsDefault"}
I changed from "obsDefault" to "obsChanged"!
{"monitoredProperty":"obsChanged"}

그러나 당신을 잃에 대한 정보를 제공 변경되지 않아,당신이 쉽게 액세스 필드에 이름입니다. 또한 당신이 변화하는 데이터 구조,위에서 언급한 바와 같고 바람직하지 않을 수 있습 또는 심지어 가능합니다. 또한,이 일에 대해서만 문자열이 지금도 하나 그것을 만들 수도 있습니다 더 많은 일반적인 하지만입니다. 또한,이를 많이 필요로의 보일러로 시작합니다. 에서 호출 사이트는 그러나,당신은 단지 포장 실제 가치에는 전화 obs. 내가 사용하는 다음과 같은 상용하여 검색할 수 있습니다.

typealias OnChange = (before: String, after: String) -> Unit

@Serializable(with = MonitoredStringSerializer::class)
class MonitoredString(initialValue: String, var onChange: OnChange?) {
    var value: String = initialValue
        set(value) {
            onChange?.invoke(field, value)

            field = value
        }

}

fun obs(value: String, onChange: OnChange? = null) = MonitoredString(value, onChange)

object MonitoredStringSerializer : KSerializer<MonitoredString> {
    override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("MonitoredString", PrimitiveKind.STRING)

    override fun serialize(encoder: Encoder, value: MonitoredString) {
        encoder.encodeString(value.value)
    }

    override fun deserialize(decoder: Decoder): MonitoredString {
        return MonitoredString(decoder.decodeString(), null)
    }
}
2021-11-24 18:19:41

현재는 유사한 접근 방식이지만,그것은 같은 느낌이 더 좋을 수 있습니다. 라 추가 단계를 만드는 방법 monitoredString 반환하는 MonitoredString 이 기능에 액세스,이가 없을 통과하는 onChange 있는 링크를 변경합니다. 의 단점을 관찰할 수"상태"를 클래스고 다음 데이터 전송할 수 있는 클래스는 직렬화의 중복의 모델 필드가 있습니다. 보 좋은 해결책이 실현하는 것을 목표로하고 내가 원하는 것은 주석으로 무언가를 생성 상용구를 사용하여 KSP.
Jan Vladimir Mostert

다른 언어로

이 페이지는 다른 언어로되어 있습니다

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................