[英]Copy most attributes from one class object to another class
Between two separate data classes, Person
and PersonRecord
, which share the same attribute names, I want an elegant way to copy the values from one class's attributes to the other's.在共享相同属性名称的两个单独的数据类
Person
和PersonRecord
之间,我想要一种优雅的方式将值从一个类的属性复制到另一个类的属性。
I have a data class, say for example Person
, that defines the business logic data of a person in the application.我有一个数据 class,例如
Person
,它定义了应用程序中人员的业务逻辑数据。
import kotlinx.serialization.Serializable
data class Person(
val id: String,
val name: String,
val age: Int,
val currentEmployment: Employment,
val workPermit: WorkPermit
)
@Serializable
data class Employment(
val employer: String,
val job: String,
val yearsWithEmployer: Double
)
@Serializable
data class WorkPermit(
val nationality: String,
val visa: String
)
I need to use these with an AWS DynamoDB client, but this question doesn't really concern DynamoDB specifically.我需要将这些与 AWS DynamoDB 客户端一起使用,但这个问题并不特别关注 DynamoDB。 I'll explain my usage below.
我将在下面解释我的用法。
For several reasons, I've decided to implement a DAO class that is essentially a copy of the class Person
, called PersonRecord
except the fields containing complex types, ie, Employment
and WorkPermit
, are stored as Strings instead.出于多种原因,我决定实现一个 DAO class,它本质上是 class
Person
的副本,称为PersonRecord
,除了包含复杂类型的字段,即, Employment
和WorkPermit
存储为字符串。 Also, all the fields are mutable and nullable.此外,所有字段都是可变且可为空的。 I had to make it this way because it's supposed to be a mapper class for DynamoDB Enhanced Client ( doc ).
我必须这样做,因为它应该是 DynamoDB 增强客户端 ( doc ) 的映射器 class 。
Annotating this class as @DynamoDbBean
defines how the client writes items into a specified table.将此 class 注释为
@DynamoDbBean
定义了客户端如何将项目写入指定的表。
package util
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable
import software.amazon.awssdk.enhanced.dynamodb.Key
import software.amazon.awssdk.enhanced.dynamodb.TableSchema
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey
@DynamoDbBean
internal data class PersonRecord(
@get: DynamoDbPartitionKey
@get: DynamoDbSortKey
var id: String? = null,
var name: String? = null,
var age: Int? = null,
var currentEmployment: String? = null,
var workPermit: String? = null,
)
class PersonDao(
ddb: DynamoDbEnhancedClient,
personTableName: String
) {
private val personTable: DynamoDbTable<PersonRecord> = ddb.table(
personTableName,
TableSchema.fromBean(PersonRecord::class.java)
)
private fun toPersonRecord(person: Person): PersonRecord =
PersonRecord(
id = person.id,
name = person.name,
age = person.age,
currentEmployment = Json.encodeToString(person.currentEmployment),
workPermit = Json.encodeToString(person.workPermit)
)
private fun toPerson(personRecord: PersonRecord): Person =
Person(
id = personRecord.id!!,
name = personRecord.name!!,
age = personRecord.age!!,
currentEmployment = Json.decodeFromString(
personRecord.currentEmployment!!
),
workPermit = Json.decodeFromString(
personRecord.workPermit!!
)
)
fun writePerson(person: Person) =
personTable.putItem(toPersonRecord(person))
fun readPerson(id: String): Person? {
val personRecord = personTable.getItem(
Key.builder()
.partitionValue(id)
.build()
)
return if (personRecord != null) toPerson(personRecord)
else null
}
}
I am using the public functions readPerson
and writePerson
to read and write the pretty Person
class, while these functions internally convert to and fro PersonRecord
.我正在使用公共函数
readPerson
和writePerson
来读写漂亮的Person
class,而这些函数在内部来回转换PersonRecord
。
Is there a way to copy between the different classes Person
and PersonRecord
more elegantly?有没有办法更优雅地在不同类
Person
和PersonRecord
之间进行复制? If, in the future, we change the shape of Person
slightly, there's a lot to change in the PersonRecord
and PersonDao
classes too.如果将来我们稍微改变
Person
的形状,那么PersonRecord
和PersonDao
类也有很多需要改变的地方。 In particular, I need a way to handle decoding String
to Employment
and WorkPermit
, and vice-versa.特别是,我需要一种将
String
解码为Employment
和WorkPermit
的方法,反之亦然。
In the example above, it'd be trivial to add a field or two, but in my actual application I'm dealing with over a dozen fields, and a bunch of unit tests intricately involved with the fields themselves.在上面的示例中,添加一个或两个字段是微不足道的,但在我的实际应用程序中,我正在处理十几个字段,以及一堆与字段本身错综复杂的单元测试。
Someone suggested to use class reflections, but I don't understand how I'd use it based on what theKotlin docs describe.有人建议使用 class 反射,但根据Kotlin 文档的描述,我不明白如何使用它。
You can try to read Person properties into a map via reflections (there is no other way) and use delegated properties feature to construct PersonRecord from that map.您可以尝试通过反射(没有其他方法)将 Person 属性读入 map 并使用委托属性功能从该 map 构造 PersonRecord。
https://kotlinlang.org/docs/delegated-properties.html#storing-properties-in-a-map https://kotlinlang.org/docs/delegated-properties.html#storing-properties-in-a-map
Here is a sample of reading via reflection https://stackoverflow.com/a/38688203/8642957这是通过反射读取的示例https://stackoverflow.com/a/38688203/8642957
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.