Десериализация GSON polymorphi c не может десериализовать свойство `type` с помощью RuntimeTypeAdapterFactory - PullRequest
0 голосов
/ 22 марта 2020

Я пытаюсь использовать адаптер типа gson для десериализации моего JSON. Я могу вернуть объект обратно десериализованным, но свойство type всегда возвращает null.

JSON:

{
"type": "rectangle",
"x": "3",
"y": "3",
"description": "this is my battle ground",
"children": [
{
  "type": "square",
  "x": "3",
  "y": "4",
  "description": "this is my arena",
  "children": [
    {
      "type": "circle",
      "x": "0",
      "y": "0",
      "radius": "3",
      "description": "this is my inner circle"
    },
    {
      "type": "circle",
      "x": "0",
      "y": "0",
      "radius": "4",
      "description": "this is my inner circle"
    },
    {
      "type": "circle",
      "x": "0",
      "y": "0",
      "radius": "5",
      "description": "this is my inner circle"
    }
   ]
  }
 ]
}

Модели:

abstract class Shape {
    abstract val type: String
    abstract val x: String
    abstract val y: String
    abstract val description: String
}

abstract class ShapeChildren : Shape() {
    abstract val children: List<Shape>
}


enum class ShapeType(val type: String) {
    SQUARE("square"),
    RECTANGLE("rectangle"),
    CIRCLE("circle")
}

data class Square(override val type: String, override val x: String, override val y: String, override val description: String, override val children: List<Shape>) : ShapeChildren()
data class Rectangle(override val type: String, override val x: String, override val y: String, override val description: String, override val children: List<Shape>) : ShapeChildren()
data class Circle(override val type: String, override val x: String, override val y: String, override val description: String, val radius: String) : Shape()

КОНФИГ. GSON:

 val jsonResponse = loadFile("mock-response/shape.json")
        val adapterFactory = RuntimeTypeAdapterFactory.of(Shape::class.java)
            .registerSubtype(ShapeChildren::class.java)
            .registerSubtype(Square::class.java, "square")
            .registerSubtype(Circle::class.java, "circle")
            .registerSubtype(Rectangle::class.java, "rectangle")
        val gson = GsonBuilder()
            .registerTypeAdapterFactory(adapterFactory)
            .create()
        val shape = gson.fromJson(jsonResponse, Shape::class.java)
        print(shape)

ВЫХОД:

Rectangle(type=null, x=3, y=3, description=this is my battle ground, children=[Square(type=null, x=3, y=4, description=this is my arena, children=[Circle(type=null, x=0, y=0, description=this is my inner circle, radius=3), Circle(type=null, x=0, y=0, description=this is my inner circle, radius=4), Circle(type=null, x=0, y=0, description=this is my inner circle, radius=5)])])

Свойство type всегда равно нулю для дочерних классов. Я даже попытался установить его, задав ему значение по умолчанию в конструкторе. Почему свойство type не заполняется правильно? что мне не хватает?

1 Ответ

1 голос
/ 07 мая 2020

Просто используйте RuntimeTypeAdapterFactory.of(Shape::class.java, "type", true) вместо RuntimeTypeAdapterFactory.of(Shape::class.java). Последний параметр - maintainType. Вам было присвоено значение false, и в этом случае свойство type удаляется из json до десериализации.

...