Я использую типичные InterfaceAdapter<T>
:
private class InterfaceAdapter<T : Any> : JsonSerializer<T>, JsonDeserializer<T> {
override fun serialize(obj: T, interfaceType: Type, context: JsonSerializationContext): JsonElement {
val wrapper = JsonObject()
wrapper.addProperty("type", obj::class.java.name)
wrapper.add("data", Gson().toJsonTree(obj))
return wrapper
}
override fun deserialize(elem: JsonElement, interfaceType: Type, context: JsonDeserializationContext): T {
val wrapper = elem as JsonObject
val typeName = get(wrapper, "type")
val data = get(wrapper, "data")
val actualType = typeForName(typeName)
return Gson().fromJson(data, actualType)
}
private fun typeForName(typeElem: JsonElement): Type {
try {
return Class.forName(typeElem.asString)
} catch (e: ClassNotFoundException) {
throw JsonParseException(e)
}
}
private operator fun get(wrapper: JsonObject, memberName: String): JsonElement {
return wrapper.get(memberName)
?: throw JsonParseException("no '$memberName' member found in what was expected to be an interface wrapper")
}
}
И я регистрирую это так для нескольких классов:
private val gson = GsonBuilder()
.registerTypeHierarchyAdapter(Inventory::class.java, InterfaceAdapter<Inventory>())
.registerTypeHierarchyAdapter(Behaviour::class.java, InterfaceAdapter<Behaviour>())
.registerTypeHierarchyAdapter(GameObject::class.java, InterfaceAdapter<GameObject>())
.create()
Когда я проверяю, что происходит во время сериализациив отладке interfaceType
- это только реализации GameObject
, а не Behaviour
или Inventory
.Несмотря на это, сериализация заканчивается без проблем.Затем я пытаюсь десериализовать то, что я только что сериализовал, и получаю это исключение:
java.lang.RuntimeException: Unable to invoke no-args constructor for interface [...].behaviour.Behaviour. Registering an InstanceCreator with Gson for this type may fix this problem.
Каким-то образом, когда я удаляю регистрацию для GameObject
, сериализуются как Behaviour
, так и Inventory
(то есть я могу на самом делесм. interfaceType
, являющуюся одной из их реализаций в отладке), но когда я добавляю ее обратно, неожиданно только GameObject
сериализуется.
Так как мне это исправить?