сериализация с помощью gson и back не работает с общими типами

Я программирую kotlin websocket и хочу отправить dtos, преобразованный в json с gson. поэтому я написал своего рода оболочку dto, которая содержит реальное dto и некоторую дополнительную информацию о dto, как и тип этого. это моя обложка dto

class WrapperDto <T : AbstractDto> { var type = "" var action = "" var dto : T = AbstractDto() as T } 

и это один из dtos, который он может содержать:

 class Person : AbstractDto() { var firstName = "" var familyName = "" } 

здесь по причинам тестирования я пытаюсь преобразовать его в json и обратно:

  val wrapperDto2 = WrapperDto<Person>() wrapperDto2.type = Person::class.simpleName!!; wrapperDto2.action = "add" val person = Person() person.firstName = "Richard" person.familyName = "Lederer" wrapperDto2.dto = person; val gson1 = Gson() val toJson = gson1.toJson(wrapperDto2) println("to json: " + toJson) val fromJson = gson1.fromJson(toJson, wrapperDto2::class.java) println("from json: " + fromJson) 

последний println никогда не вызывается, и я получаю следующее сообщение об ошибке:

 java.lang.IllegalArgumentException: Can not set at.richardlederer.contactmanager.dto.AbstractDto field at.richardlederer.contactmanager.dto.WrapperDto.dto to com.google.gson.internal.LinkedTreeMap at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) 

Как я могу решить эту проблему?

Это связано с типом стирания дженериков . Для получения информации о типе во время выполнения вам необходимо использовать TokenType .

 val fromJson = gson1.fromJson<WrapperDto<Person>>(toJson, object: TypeToken<WrapperDto<Person>>() {}.type) 

Вы также можете создать функцию расширения следующим образом:

 inline fun <reified T> fromJson(json: String): T = Gson().fromJson<T>(json, object: TypeToken<T>() {}.type) 

Таким образом, вы можете позвонить из fromJson таким образом:

 val fromJson = fromJson<WrapperDto<Person>>(toJson) //Or val fromJson: WrapperDto<Person> = fromJson(toJson) //Type inferred