Inheritance/polymorphic serialization
See original GitHub issueI have the following hierarchy:
@Serializable
sealed class Search(@SerialName("type") private var searchType: SearchType,
@Transient open val table: String = "",
@Transient open val index: String? = null,
@Transient open val filters: List<QueryCondition> = listOf(),
@Transient open val order: Order = Order.DESC) {
fun isAscOrdered(): Boolean {
return order == Order.ASC
}
}
@Serializable
class QuerySearch(override val table: String,
override val index: String?,
val keys: List<QueryCondition>,
override val filters: List<QueryCondition>,
override val order: Order) : Search(SearchType.QUERY, table, index, filters, order) {
...
}
@Serializable
class ScanSearch(override val table: String,
override val index: String?,
override val filters: List<QueryCondition>) :
Search(SearchType.SCAN, table, index, filters, Order.ASC) {
...
}
And it already looks “ugly” in order to do the proper serialization, i.e. have to mark parent properties as open
, and override
them (in order to make them properties, as required by the serialization library) in the children.
Also in order to not have parent properties duplicated in the output JSON, have to mark them @Transient
, but it then requires to set the default values (where there are no really meaningful default values).
Only then it produces the proper JSON, like the one below:
{
"type": "QUERY",
"table": "Table A",
"index": "Index A",
"keys": [
{
"name": "Id",
"type": "NUMBER",
"operator": "EQ",
"values": [
"10"
]
}
],
"filters": [
{
"name": "Timestamp",
"type": "NUMBER",
"operator": "BETWEEN",
"values": [
"100",
"200"
]
},
{
"name": "Name",
"type": "STRING",
"operator": "BEGINS_WITH",
"values": [
"Test"
]
}
],
"order": "ASC"
}
Although when deserialize the JSON back to the class, the parent properties are set to the default values instead of the values from the child class.
And moreover don’t know how to do the polymorphic deserialization, i.e. using the discriminator value, like “type” property.
Is then this library suitable for the above use case, or it is the ultimate end goal, but it is not ready yet to handle this?
Or this library was specifically designed in mind to work only with data
classes?
Here is the unit test to produce the JSON above:
class SearchSpec : StringSpec({
"serialize query search" {
val search = QuerySearch(
"Table A",
"Index A",
listOf(QueryCondition("Id", Type.NUMBER, Operator.EQ, listOf("10"))),
listOf(QueryCondition("Timestamp", Type.NUMBER, Operator.BETWEEN, listOf("100", "200")),
QueryCondition("Name", Type.STRING, Operator.BEGINS_WITH, listOf("Test"))),
Order.ASC)
val data = Json.stringify(QuerySearch.serializer(), search)
println(data)
val parse = Json.parse(Search.serializer(), data) // Obviously this line fails,
// val parse = Json.parse(QuerySearch.serializer(), data) // but this works, but results in the default properties for the parent Search class
parse shouldBe search
}
})
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:13 (3 by maintainers)
Top GitHub Comments
Inheritance doesn’t seem to work at all…
==> IllegalStateException: Class Apricot have constructor parameters which are not properties and therefore it is not serializable automatically
AND
==> IllegalStateException: class Apricot has duplicate serial name of property name, either in it or its parents.
i’m encountering the same issue, i’m using a class that inherits from an abstract class but with with its own variables (they aren’t open nor abstract), i can’t alter the super class since its from a library, but i do need the variables to be encoded aswell, any suggestions?