This may work for you - create your own Spring Data Converter
First, imagine a general way to store the data of ProductOption
in a data type that Mongo can represent, e.g. Map<String,Any>
that contains nested Map<String,Any>
. Then remove the inner class:
@Document("Product")
data class Product(
val id: Int,
val options: List<ProductOption>,
)
Now you need an interface to link the real ProductOptions together for types 1,2,3,4,5 and then concrete classes for each of them
interface ProductOption {
val type: Int
val properties: Any
}
data class ProductOption1(
override val type: Int = 1,
override val properties: Property1,
) : ProductOption {
data class Property1(
val one: String,
)
}
data class ProductOption2(
override val type: Int = 2,
override val properties: Property2,
) : ProductOption {
data class Property2(
val a: String,
val b: String,
)
}
etc...
Then you need to create a converter that takes these concrete classes that implement ProductOption
and converts them to/from what get stored in Mongo: ProductOptionGeneral
import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import org.springframework.data.convert.WritingConverter
class MapToProductOptionConverter : Converter<Map<String,Any>, ProductOption> {
override fun convert(source: Map<String,Any>): ProductOption? {
val properties = source["properties"] as Map<String, Any>
when (source["type"] as Int) {
1 -> {
ProductOption1(
properties = ProductOption1.Property1(
one = properties["one"] as String
)
)
}
else -> TODO()
}
}
}
@WritingConverter
class ProductOptionToMapConverter : Converter<ProductOption, Map<String,Any>> {
override fun convert(source: ProductOption): Map<String,Any>? {
TODO()
}
}
Lastly register your converters
@Configuration
@EnableMongoRepositories
class MongoConfig {
@Bean
fun customConversions(): MongoCustomConversions {
return MongoCustomConversions(
listOf(
MapToProductOptionConverter(),
ProductOptionToMapConverter(),
)
)
}
(If you had asked about handling JSON deserialization into a polymorphic class structure, this is possible in a much simpler way. This could be wholly different approach for you. You'd retrieve the data from Mongo as a BSON object, convert to JSON and use Jackson's ObjectMapper in the way I describe in this Stackoverflow Answer: https://stackoverflow.com/a/72106352/1847378)