I have an abstract class "Elem" with a bunch of children (TXT, IMG, EDT ...). They all have contructors.
I need to parse in json an Object contaning a list of children of an abstract class
abstract class Elem(
var content : String,
var condition : String = ""
){
open fun instantiate(){
}
}
class TXT(content: String) : Elem(content) {
override fun instantiate() {
//Some work
}
}
class BTN(content: String, private val additional : String) : Elem(content) {
override fun instantiate() {
//Some work
}
}
...
EDIT :
I tried to used the AbstractElementAdapter
, as shown here
Here the new code to parse a JSON
val e = MyObject(/*Some stuff,*/listOf(TXT("Hello"), IMG("world.png"))))
val gsonBuilder = GsonBuilder()
gsonBuilder.registerTypeAdapter(EtapElem::class.java, JsonSerializer<EtapElem>{
src, _, context ->
val result = JsonObject()
result.add("type", JsonPrimitive(src.javaClass.simpleName))
result.add("elem", context.serialize(src, src.javaClass))
return@JsonSerializer result
})
val jsonPretty: String = gsonBuilder .setPrettyPrinting().create().toJson(e)
The json looks fine
{
//Some stuff,
"elems": [
{
"type": "TXT",
"elem": {
"content": "Hello?",
"condition": ""
}
},
{
"type": "IMG",
"elem": {
"content": "world.png",
"condition": ""
}
}
]
}
Now the read :
val gsonBuilder = GsonBuilder()
gsonBuilder.registerTypeAdapter(EtapElem::class.java, JsonDeserializer<EtapElem>{
json, _, context ->
val jsonObject = json.asJsonObject
val type = jsonObject["type"].asString
val element = jsonObject["elem"]
return@JsonDeserializer try {
context.deserialize(element, Class.forName("com.package.path.elem.$type"))
} catch (cnfe: ClassNotFoundException) {
throw JsonParseException("Unknown element type: $type", cnfe)
}
})
val outtype = object : TypeToken<MyObject>() {}.type
val s : Scenario = gsonBuilder.create().fromJson(jsonFileString, outtype)
I have an exception thrown in read :
java.lang.ClassCastException: class com.package.path.elem.TXT cannot be cast to class java.lang.Void (com.package.path.elem.TXT is in unnamed module of loader 'app'; java.lang.Void is in module java.base of loader 'bootstrap')