1

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')

Foxhunt
  • 764
  • 1
  • 9
  • 23
  • 2
    Could you include the code that parses the JSON into these objects? – sanitizedUser Jun 27 '21 at 13:39
  • 1
    It is a raw use of Gson. Included ! – Foxhunt Jun 27 '21 at 13:45
  • What is `myobject()`? Where is the definition of that function? – sanitizedUser Jun 27 '21 at 13:47
  • Look at this [question](https://stackoverflow.com/questions/16000163/using-gson-and-abstract-classes), maybe there is something that can help you. Otherwise I suggest you create functional example that can be run on [REPLit](https://replit.com/) and post the link to it here so we can debug it properly. – sanitizedUser Jun 27 '21 at 13:55
  • You're right, all of them have constructors, but none of them have a no-arg constructor. – broot Jun 27 '21 at 14:16
  • I suppose i need an ``AbstractElementAdapter`` to make a difference between elements. I will try this http://ovaraksin.blogspot.com/2011/05/json-with-gson-and-abstract-classes.html – Foxhunt Jun 27 '21 at 17:25
  • I have done a Replit, but i cannot make it compile properly https://replit.com/join/pbrduqvnqn-fx73 – Foxhunt Sep 29 '21 at 14:39

0 Answers0