Reputation: 2013
I am trying to use gson type adapter to deserialize my JSON. I am able to get the object back deserialized but the type property always returns 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"
}
]
}
]
}
Models:
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()
CONFIG 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)
OUTPUT:
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)])])
The type
property is always null for child classes. I even tried to set it by giving it a default value in the constructor. Why does the type property not get populated correctly? what am I missing?
Upvotes: 1
Views: 822
Reputation: 2969
Simply use RuntimeTypeAdapterFactory.of(Shape::class.java, "type", true)
instead of RuntimeTypeAdapterFactory.of(Shape::class.java)
. The last parameter is maintainType
. You had it set to false
, in which case the type property is removed from the json prior to deserialization.
Upvotes: 2