Serialization Kotlin中的单例序列化
我想知道在Kotlin中是否可以对声明对象进行反序列化(还原属性值),而不必手动分配属性或诉诸反射。下面的代码片段进一步解释:Serialization Kotlin中的单例序列化,serialization,singleton,kotlin,Serialization,Singleton,Kotlin,我想知道在Kotlin中是否可以对声明对象进行反序列化(还原属性值),而不必手动分配属性或诉诸反射。下面的代码片段进一步解释: object Foo: Serializable { var propOne: String = "" // ... fun persist() { serialize(this) // no problem with serialization } fun restore(bytes: By
object Foo: Serializable {
var propOne: String = ""
// ...
fun persist() {
serialize(this)
// no problem with serialization
}
fun restore(bytes: ByteArray) {
val fooObj: Foo = deserialize(bytes) as Foo
// It seems Kotlin allows us to use singleton as type!
// obvioulsly either of the following is wrong:
// this = fooObj
// Foo = fooObj
// ... is there a way to 'recover' the singleton (object) other than
// manual assignment of properties (or reflection) ???
}
}
无法将全局引用重新分配给具有新实例的singleton。最多可以在序列化期间写出属性,然后在反序列化时直接读取属性并改变原始对象中的状态。通过直接指定或反射将属性指定给对象需要自定义代码。如果您创建自己的单例机制来保存一个实例,您可以将其交换为另一个反序列化的实例,这会更好。遇到同样的问题,希望与您分享我的解决方案:
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import java.io.File
import java.lang.reflect.Modifier
typealias ObjMap = HashMap<String, Any?>
fun <T : Any> T.getInstance() : Any? {
val target = if(this is Class<*>) this else javaClass
return target.getDeclaredField("INSTANCE")?.get(null)
}
class ObjectHelper {
companion object {
val mapper = ObjectMapper().apply {
enable(SerializationFeature.INDENT_OUTPUT)
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
}
fun objectToMap(obj: Any): ObjMap {
var res = ObjMap()
val instance = obj.getInstance()
val o = instance ?: obj
o.javaClass.declaredFields.forEach {
if(it.name != "INSTANCE") {
it.isAccessible = true
val value = if(Modifier.isStatic(it.modifiers)) it.get(null) else it.get(o)
res[it.name] = value
}
}
o.javaClass.classes.forEach {
res[it.simpleName] = objectToMap(it)
}
return res
}
fun saveObject(path: String, obj: Any) {
mapper.writeValue(File(path), objectToMap(obj))
}
fun loadObject(path: String, obj: Any) {
val json = mapper.readValue<HashMap<*,*>>(File(path), HashMap::class.java) as ObjMap
loadObject(obj, json)
}
fun loadObject(obj: Any, props: ObjMap) {
val objectParam = mapper.writeValueAsString(props)
mapper.readValue(objectParam, obj::class.java)
obj.javaClass.classes.forEach {
val instance = it.getInstance()
val map = props[it.simpleName]
if(map != null && instance != null) {
loadObject(instance, map as ObjMap)
}
}
}
}
}
结果将是“aaa” 你确定你不想在这里上普通课吗?带有变量的单例基本上是全局可变状态。@marstran:setter可以设置为
私有
或内部
。它仍然是全局可变状态。它可以被全球访问,也可以变异。是的,两者都可能非常糟糕。
object TestObj {
var f1: String = "f1"
var f2: String = "f2"
object TestObj_2 {
var f1: String = "f1_1"
var f2: String = "f2_2"
}
}
TestObj.f1 = "aaa"
saveObject("out.json", TestObj)
TestObj.f1 = "bbb"
loadObject("out.json", TestObj)
println(TestObj.f1)