Annotations
Annotations based usage of the ShapeShift library.
Basic Mapping
We start by defining two classes, our source class SimpleEntity
and our destination class SimpleEntityDisplay
.
data class SimpleEntity(
val name: String,
val description: String,
val privateData: String
)
data class SimpleEntityDisplay(
val name: String = "",
val description: String = ""
)
We can now start adding our annotations to the SimpleEntity
class. In this example, we want to map the name
and description
fields to the name
and description
fields of the SimpleEntityDisplay
class, but not the privateData
field.
To achieve this, we will use the @MappedField annotation on both of these fields. Additionally, we will define @DefaultMappingTarget
on the SimpleEntity
class, which will indicate that all fields annotated with @MappedField
that do not specify a target should be mapped to the SimpleEntityDisplay
class.
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField
val name: String,
@MappedField
val description: String,
val privateData: String
)
Default Mapping Target
@DefaultMappingTarget
on a class, indicates that all fields annotated with @MappedField
that do not specify a target should be mapped to this class by default.
Mapping Target
The mapping target comes into play when you want to map a single source to multiple destinations. The target
attribute is used to indicate to which class the field should be mapped. If no target is specified the target will be determined by the @DefaultMappingTarget
on the class.
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField
@MappedField(target = SimpleEntityExport::class)
val name: String,
@MappedField
val description: String
)
In the above code name is mapped once to the SimpleEntityDisplay
class using the default mapping target, and once to the SimpleEntityExport
class using the target
attribute.
data class SimpleEntityDisplay(
val name: String = "",
val description: String = ""
)
data class SimpleEntityExport(
val name: String = ""
)
Map To Field
By default each @MappedField
is mapped to a field with the same name in the target class. To change it use the mapTo
value. For example:
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField(mapTo = "fullName")
val name: String
)
data class SimpleEntityDisplay(
val fullName: String = ""
)
Map From Field
The field name to map the value from.
Field Level
When mapFrom
is used at the field level, it allows for mapping of nested values.
@DefaultMappingTarget(AdvancedEntityDisplay::class)
data class AdvancedEntity(
// This field will be mapped to the "firstChildName" field in the default target class
@MappedField(mapFrom = "childName", mapTo = "firstChildName")
val firstChild: AdvancedChildEntity,
// This field will be mapped to the "secondChildName" field in the default target class
@MappedField(mapFrom = "childName", mapTo = "secondChildName")
val secondChild: AdvancedChildEntity
)
As you can see above, we use the mapFrom
attribute to access the childName
field in AdvancedChildEntity
.
data class AdvancedChildEntity(
val childName: String
)
And we use the mapTo
attribute to map the values to the appropriate fields in AdvancedEntityDisplay.
data class AdvancedEntityDisplay(
val firstChildName: String = "",
val secondChildName: String = ""
)
Type Level
The @MappedField
annotation can also be used at the type level. When used at the type level, the mapFrom
attribute is required to indicate the name of the field to use, if left empty an exception will be thrown.
@MappedField(target = SimpleEntityDisplay::class, mapFrom = "firstName")
@MappedField(target = SimpleEntityDisplay::class, mapFrom = "lastName")
data class SimpleEntity(
val firstName: String,
val lastName: String,
)
data class SimpleEntityDisplay(
val firstName: String = "",
val lastName: String = ""
)
Transformer
Field transformers are a way to transform a field from one type to another when mapping it to a destination class. More about the ins-and-outs of transformers is available here:
TransformersTo configure a transformer for a field use the transformer
attribute. The transformer
attribute receives the transformer's class.
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField(transformer = StringToListMappingTransformer::class, mapTo = "stringList")
val commaDelimitedString: String
)
data class SimpleEntityDisplay(
val stringList: List<String> = emptyList()
)
Auto Mapping
Auto mapping is used to reduce the amount of boiler-place code required to configure mapping between two classes. More info about auto mapping is available here:
Auto MappingAuto mapping can be added using the @AutoMapping
annotation.
@AutoMapping(SimpleEntityDisplay::class, strategy = AutoMappingStrategy.BY_NAME)
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
val id: String,
val name: String,
val birthDate: Date,
val email: String,
val telephone: String
)
The @AutoMapping
annotation has two attributes:
target
- If no target is added then the auto mapping will be configured to any target class. It is possible to add multiple@AutoMapping
annotation for multiple target classes.strategy
- The auto mapping strategy. Default valueNONE
.
Mapping Condition
Conditions are used to determine wether a field should be mapped according to certain logic. More info about conditions is available here:
ConditionsA condition can be added to annotation mapping using the condition
attribute.
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField(condition = NotBlankStringCondition::class)
val name: String
)
We mapped the name field and added a condition for the mapping.
data class SimpleEntityDisplay(
val name: String = ""
)
The condition receives context with the original value of the field and checks that it is not null or blank.
class NotBlankStringCondition : MappingCondition<String> {
override fun isValid(context: MappingConditionContext<String>): Boolean {
return !context.originalValue.isNullOrBlank()
}
}
Override Mapping Strategy
The overrideMappingStrategy
attribute allows you to override the default mapping strategy configured on the ShapeShift
instance.
@DefaultMappingTarget(SimpleEntityDisplay::class)
data class SimpleEntity(
@MappedField(overrideMappingStrategy = MappingStrategy.MAP_ALL)
val name: String
)
More info about mapping strategy is available here:
Mapping StrategyLast updated
Was this helpful?