GSON: невозможно десериализовать (используя несколько TypeAdapters) - PullRequest
0 голосов
/ 23 апреля 2019

Я использую типичные 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 сериализуется.

Так как мне это исправить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...