HeterogeneousItemConverter

An item converter which handles heterogeneous (i.e., incongruent) data types by way of a string discriminator attribute identified by typeAttribute. Each type name stored in typeAttribute identifies the delegate converter (from subConverters) used for that item.

This converter is particularly (although not solely) useful for mapping polymorphic structures. For example, given a class hierarchy:

sealed interface Vehicle

@DynamoDbItem
data class Car(
@DynamoDbPartitionKey val id: Int,
val manufacturer: String,
val model: String,
val year: Int,
) : Vehicle

@DynamoDbItem
data class Bike(
@DynamoDbPartitionKey val id: Int,
val manufacturer: String,
val gears: Int,
val isElectric: Boolean,
) : Vehicle

A heterogeneous item converter can be constructed by registering a converter for each type:

val vehicleConverter = HeterogeneousItemConverter<Vehicle>(typeAttribute = "type") {
instanceOf("car", CarConverter)
instanceOf("bike", BikeConverter)
}

See HeterogeneousItemConverter.Builder for details on how objects are matched to registered types.

Objects mapped in this manner will use only the attributes relevant to their specific type, plus the typeAttribute. For example, given the following items and PutItem calls:

val vehicles = listOf(
Car(1, "Ford", "Model T", 1928),
Bike(2, "Schwinn", 10, false),
Car(3, "Edsel", "Corsair", 1958),
Bike(4, "Kuwahara", 1, false),
)

val table = ... // some table which uses the vehicleConverter from above in its schema

vehicles.forEach { vehicle ->
table.putItem(vehicle)
}

Items would be persisted in the table as:

idtypemanufacturermodelyeargearsisElectric
1carFordModel T1928
2bikeSchwinn10false
3carEdselCorsair1958
4bikeKuwahara1false

Converters may alternatively be constructed with an explicit typeMapper function via the primary constructor. This is useful when the type name isn't determined by the object's class (e.g., when it's derived from a property value).

All conversion failures (unmapped objects, missing/non-string/unknown type attributes, and discriminator conflicts) throw IllegalArgumentException.

Type Parameters

T

The common type ancestor for all subtypes handled by this converter. This may be a base class, interface, or even Any.

Constructors

Link copied to clipboard
constructor(typeMapper: (T) -> String, typeAttribute: String, subConverters: Map<String, ItemConverter<out T>>)

Initializes a new HeterogeneousItemConverter with an explicit type-mapping function

Types

Link copied to clipboard
class Builder<T : Any>

A builder for a HeterogeneousItemConverter which maps objects to type names according to their class. Obtain an instance via the HeterogeneousItemConverter(typeAttribute) { ... } factory function.

Properties

Link copied to clipboard

A map of type names to the ItemConverter instances which handle them. Each converter may handle T itself or any subtype of T (e.g., generated converters for individual subclasses).

Link copied to clipboard

The name of the attribute in which to store/read type information. This attribute will be present for every item persisted via this converter.

Link copied to clipboard
val typeMapper: (T) -> String

A function which accepts an instance of the common type T and returns the string identifier for the type. This identifier is written/read from the attribute identified by typeAttribute and used as a lookup key in subConverters.

Functions

Link copied to clipboard
open override fun convertLeft(from: Item): T
Link copied to clipboard
open override fun convertRight(from: T): Item

Inherited functions

Link copied to clipboard
fun <V : Any> ValueConverter<V>.asNullable(nullValueConverter: ValueConverter<Nothing?> = NullValueConverter): ValueConverter<V?>
Link copied to clipboard
fun <T, PK : KeyType> ItemConverter<T>.withKeySpec(partitionKey: KeySpec<PK>, attributes: Attributes = emptyAttributes()): ItemSchema.PartitionKey<T, PK>

Associate this ItemConverter with a KeySpec for a partition key to form a complete ItemSchema

fun <T, PK : KeyType, SK : KeyType> ItemConverter<T>.withKeySpec(partitionKey: KeySpec<PK>, sortKey: KeySpec<SK>, attributes: Attributes = emptyAttributes()): ItemSchema.CompositeKey<T, PK, SK>

Associate this ItemConverter with KeySpec instances for a composite key to form a complete ItemSchema