CustomStructSchema
A flexible schema for custom serialization of objects with user-defined encoding logic.
CustomStructSchema provides maximum flexibility for serializing objects by allowing users to define exactly how their objects should be decomposed into primitive components. This is particularly useful for:
Legacy Objects: Classes that can't be modified to use reflection-based serialization
Optimized Encoding: Custom logic to minimize serialized size or improve performance
Data Transformation: Converting objects during serialization (e.g., coordinate transformations)
Selective Serialization: Including only specific fields or computed values
Version Compatibility: Maintaining backward compatibility with different object versions
Architecture
The schema uses a component-based approach where:
Objects are decomposed into a list of primitive components via the encoder function
Each component has a corresponding name and schema for serialization
Components are serialized in the order they appear in componentNames
A type string is automatically prepended to identify the object type
Binary Format
Schema Encoding:
[4 bytes: tag] [4 bytes: component count]
[4 bytes: ".type" length] [".type" bytes] [StringSchema]
[4 bytes: name1 length] [name1 bytes] [schema1]
[4 bytes: name2 length] [name2 bytes] [schema2]
...Object Encoding:
[4 bytes: type length] [type string bytes]
[component1 data] [component2 data] ...Usage Examples
Basic Usage
data class Person(val name: String, val age: Int, val email: String)
val personSchema = CustomStructSchema<Person>(
type = "Person",
componentNames = listOf("name", "age", "email"),
componentSchemas = listOf(StringSchema, IntSchema, StringSchema),
encoder = { person -> listOf(person.name, person.age, person.email) }
)Data Transformation
val transformedSchema = CustomStructSchema<Person>(
type = "NormalizedPerson",
componentNames = listOf("displayName", "ageCategory"),
componentSchemas = listOf(StringSchema, StringSchema),
encoder = { person ->
listOf(
person.name.uppercase(),
when {
person.age < 18 -> "MINOR"
person.age < 65 -> "ADULT"
else -> "SENIOR"
}
)
}
)Selective Field Serialization
val minimalSchema = CustomStructSchema<ComplexObject>(
type = "Essential",
componentNames = listOf("id", "status"),
componentSchemas = listOf(LongSchema, StringSchema),
encoder = { obj -> listOf(obj.id, obj.currentStatus.name) }
)Parameters
The type of objects this schema can serialize
A string identifier for this object type, written to the log for identification
Names of the components in serialization order. Used for schema documentation.
Schemas for each component, must match the order of componentNames
Function that converts objects of type T into a list of primitive components
Throws
if componentNames and componentSchemas have different sizes
Types
Properties
Names of the serialized components in order.
Schemas for each component in the same order as componentNames.
Number of bytes required to encode this schema's metadata.