sun*_*one 50 java modelmapper kotlin
我想将一些"数据"类对象转换/映射到类似的"数据"类对象.例如,Web表单的类到数据库记录的类.
data class PersonForm(
val firstName: String,
val lastName: String,
val age: Int,
// maybe many fields exist here like address, card number, etc.
val tel: String
)
// maps to ...
data class PersonRecord(
val name: String, // "${firstName} ${lastName}"
val age: Int, // copy of age
// maybe many fields exist here like address, card number, etc.
val tel: String // copy of tel
)
Run Code Online (Sandbox Code Playgroud)
我在Java中使用ModelMapper进行此类工作,但由于数据类是final(ModelMapper创建CGLib代理以读取映射定义),因此无法使用它.当我们打开这些类/字段时,我们可以使用ModelMapper,但是我们必须手动实现"data"类的功能.(参见ModelMapper示例:https://github.com/jhalterman/modelmapper/blob/master/examples/src/main/java/org/modelmapper/gettingstarted/GettingStartedExample.java)
如何在Kotlin中映射这样的"数据"对象?
更新: ModelMapper自动映射具有相同名称的字段(如tel - > tel),而不映射声明.我想用Kotlin的数据类来做.
更新: 每个类的目的取决于应用程序的类型,但这些应用程序可能位于应用程序的不同层.
例如:
这些类是相似的,但不一样.
我想避免正常的函数调用,原因如下:
当然,有一个具有类似功能的库,但也欢迎Kotlin功能的信息(如在ECMAScript中传播).
mfu*_*n26 43
最简单(最好的?):
fun PersonForm.toPersonRecord() = PersonRecord(
name = "$firstName $lastName",
age = age,
tel = tel
)
Run Code Online (Sandbox Code Playgroud)反思(不是很好的表现):
fun PersonForm.toPersonRecord() = with(PersonRecord::class.primaryConstructor!!) {
val propertiesByName = PersonForm::class.memberProperties.associateBy { it.name }
callBy(args = parameters.associate { parameter ->
parameter to when (parameter.name) {
"name" -> "$firstName $lastName"
else -> propertiesByName[parameter.name]?.get(this@toPersonRecord)
}
})
}
Run Code Online (Sandbox Code Playgroud)缓存反射(性能良好但不如#1快):
open class Transformer<in T : Any, out R : Any>
protected constructor(inClass: KClass<T>, outClass: KClass<R>) {
private val outConstructor = outClass.primaryConstructor!!
private val inPropertiesByName by lazy {
inClass.memberProperties.associateBy { it.name }
}
fun transform(data: T): R = with(outConstructor) {
callBy(parameters.associate { parameter ->
parameter to argFor(parameter, data)
})
}
open fun argFor(parameter: KParameter, data: T): Any? {
return inPropertiesByName[parameter.name]?.get(data)
}
}
val personFormToPersonRecordTransformer = object
: Transformer<PersonForm, PersonRecord>(PersonForm::class, PersonRecord::class) {
override fun argFor(parameter: KParameter, data: PersonForm): Any? {
return when (parameter.name) {
"name" -> with(data) { "$firstName $lastName" }
else -> super.argFor(parameter, data)
}
}
}
fun PersonForm.toPersonRecord() = personFormToPersonRecordTransformer.transform(this)
Run Code Online (Sandbox Code Playgroud)data class PersonForm(val map: Map<String, Any?>) {
val firstName: String by map
val lastName: String by map
val age: Int by map
// maybe many fields exist here like address, card number, etc.
val tel: String by map
}
// maps to ...
data class PersonRecord(val map: Map<String, Any?>) {
val name: String by map // "${firstName} ${lastName}"
val age: Int by map // copy of age
// maybe many fields exist here like address, card number, etc.
val tel: String by map // copy of tel
}
fun PersonForm.toPersonRecord() = PersonRecord(HashMap(map).apply {
this["name"] = "${remove("firstName")} ${remove("lastName")}"
})
Run Code Online (Sandbox Code Playgroud)kli*_*mat 16
这是你在找?
data class PersonRecord(val name: String, val age: Int, val tel: String){
object ModelMapper {
fun from(form: PersonForm) =
PersonRecord(form.firstName + form.lastName, form.age, form.tel)
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
val personRecord = PersonRecord.ModelMapper.from(personForm)
Run Code Online (Sandbox Code Playgroud)
小智 6
使用MapStruct:
@Mapper
interface PersonConverter {
@Mapping(source = "phoneNumber", target = "phone")
fun convertToDto(person: Person) : PersonDto
@InheritInverseConfiguration
fun convertToModel(personDto: PersonDto) : Person
}
Run Code Online (Sandbox Code Playgroud)
使用:
val converter = Mappers.getMapper(PersonConverter::class.java) // or PersonConverterImpl()
val person = Person("Samuel", "Jackson", "0123 334466", LocalDate.of(1948, 12, 21))
val personDto = converter.convertToDto(person)
println(personDto)
val personModel = converter.convertToModel(personDto)
println(personModel)
Run Code Online (Sandbox Code Playgroud)
https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-kotlin
使用模型映射器
/** Util.kt **/
class MapperDto() : ModelMapper() {
init {
configuration.matchingStrategy = MatchingStrategies.LOOSE
configuration.fieldAccessLevel = Configuration.AccessLevel.PRIVATE
configuration.isFieldMatchingEnabled = true
configuration.isSkipNullEnabled = true
}
}
object Mapper {
val mapper = MapperDto()
inline fun <S, reified T> convert(source: S): T = mapper.map(source, T::class.java)
}
Run Code Online (Sandbox Code Playgroud)
用法
val form = PersonForm(/** ... **/)
val record: PersonRecord = Mapper.convert(form)
Run Code Online (Sandbox Code Playgroud)
如果字段名称不同,您可能需要一些映射规则。请参阅入门
PS:使用kotlin no-args插件为您的数据类提供默认的无参数构造函数
| 归档时间: |
|
| 查看次数: |
35111 次 |
| 最近记录: |