1

Trying to parse a complex json object using Gson. Here are the data classes that are failing:

data class Advisor(
    val students: List<Student>?,
)

sealed class Student {
    data class BusinessMajor(val name: String, val items: List<Courses>) : Student()
    data class ArtsMajor(val name: String, val items: List<Courses>) : Student()
}

At runtime, I get this exception:

java.lang.RuntimeException: Failed to invoke private com.mysite.myapp.ApiResponse$Student() with no args

I've read that this can be created by trying to parse abstract classes, but all the posts I've read are for Java. I don't see anything that helps with Kotlin data classes, particularly wrapped with a sealed class.

Any help is appreciated. Thanks.

AndroidDev
  • 20,466
  • 42
  • 148
  • 239

2 Answers2

3

Sealed types classes cannot be instantiated : see here

A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.

Sealed classes are not allowed to have non-private constructors (their constructors are private by default).

Community
  • 1
  • 1
Gremi64
  • 1,534
  • 12
  • 19
1

It should work the same as in Java. Adapting the example from https://stackoverflow.com/a/21641225/9204:

val rta = RuntimeTypeAdapterFactory.of(Student::class.java)
    .registerSubtype(Student.BusinessMajor::class.java)
    .registerSubtype(Student.ArtsMajor::class.java)
val gson = new GsonBuilder()
    .registerTypeAdapterFactory(rta)
    .create()

But:

  1. This way you need to write a factory for every sealed class. Maybe there is a helper library to avoid this problem, but if so I haven't found it.

  2. See also Why Kotlin data classes can have nulls in non-nullable fields with Gson?

On the whole, I'd strongly consider using Moshi or another Kotlin-aware JSON library.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487