将类映射在一起时处理类中的 null 类型的最佳做法



我正在使用 Kotlin 1.30。我有以下将从 API 填充的实体类。并且某些属性在 API 中可能是空的,所以我使用安全的空类型声明了它们。

但是,我会将此实体类映射到我的域模型类。只是想知道处理空类型的最佳方法是什么?

关于在映射类时如何执行此操作,我有 2 个想法。

  1. 将所有等效属性声明为安全 NULL 类型
  2. 使用 ELIVS 运算符返回空字符串或空列表

在下面的代码片段中,我使用了猫王运算符。只是想知道这方面的最佳实践是什么?

class LoginResponseDomainMapperImp : LoginResponseDomainMapper {
    override fun map(entity: LoginResponseEntity): LoginResponse {
        return LoginResponse(
            entity.token ?: "",
            mapUsers(entity.user),
            mapEnterprises(entity.enterprises ?: emptyList()),
            mapVendors(entity.vendors ?: emptyList()))
    }
    private fun mapUsers(userEntity: UserEntity?): User {
        return User(
            userEntity?.id,
            userEntity?.email,
            userEntity?.firstName,
            userEntity?.lastName,
            userEntity?.phone,
            userEntity?.address,
            userEntity?.dob,
            userEntity?.customer,
            userEntity?.enterpriseIds ?: emptyList(),
            userEntity?.vendorIds ?: emptyList())
    }
    private fun mapEnterprises(enterprisesEntity: List<EnterprisesEntity>): List<Enterprises> {
        val enterpriseList = mutableListOf<Enterprises>()
        enterprisesEntity.forEach {
            val enterprise = Enterprises(
                it.id,
                it.enterpriseName,
                it.typeLabel,
                it.country,
                it.imageId,
                it.managers,
                it.members,
                it.stripe,
                it.locations)
            enterpriseList.add(enterprise)
        }
        return enterpriseList.toList()
    }
    private fun mapVendors(vendorsEntity: List<VendorsEntity>): List<Vendors> {
        val vendorList = mutableListOf<Vendors>()
        vendorsEntity.forEach {
            val vendor = Vendors(
                it.id,
                it.vendorName,
                it.typeLabel,
                it.userRole,
                it.latitude,
                it.longitude,
                it.partner,
                it.country,
                it.imageId,
                it.stripe)
            vendorList.add(vendor)
        }
        return vendorList.toList()
    }
}

将从 API 填充的实体类,因此其中任何一个都可能为 null

data class LoginResponseEntity(
    @SerializedName("token") val token: String?,
    @SerializedName("user") val user: UserEntity?,
    @SerializedName("enterprises") val enterprises: List<EnterprisesEntity>?,
    @SerializedName("vendors") val vendors: List<VendorsEntity>?)
data class UserEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("email") val email: String?,
    @SerializedName("first_name") val firstName: String?,
    @SerializedName("last_name") val lastName: String?,
    @SerializedName("phone") val phone: String?,
    @SerializedName("address") val address: String?,
    @SerializedName("dob") val dob: String?,
    @SerializedName("customer") val customer: String?,
    @SerializedName("enterprise_ids") val enterpriseIds: List<String>?,
    @SerializedName("vendor_ids") val vendorIds: List<String>?)
data class EnterprisesEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("enterprise_name") val enterpriseName: String?,
    @SerializedName("type_label") val typeLabel: String?,
    @SerializedName("referral_code") val referralCode: String?,
    @SerializedName("country") val country: String?,
    @SerializedName("image_id") val imageId: String?,
    @SerializedName("managers") val managers: List<String>?,
    @SerializedName("members") val members: List<String>?,
    @SerializedName("stripe") val stripe: Boolean,
    @SerializedName("locations") val locations: List<String>?)
data class VendorsEntity(
    @SerializedName("id") val id: String?,
    @SerializedName("vendor_name") val vendorName: String?,
    @SerializedName("type_label") val typeLabel: String?,
    @SerializedName("user_role") val userRole: String?,
    @SerializedName("latitude") val latitude: Float,
    @SerializedName("longitude") val longitude: Float,
    @SerializedName("partner") val partner: Boolean,
    @SerializedName("country") val country: String?,
    @SerializedName("image_id") val imageId: String?,
    @SerializedName("stripe") val stripe: Boolean)

域中的数据模型类,最好将它们声明为安全空类型吗?

data class LoginResponse(
    val token: String,
    val user: User?,
    val enterprises: List<Enterprises>,
    val vendors: List<Vendors>)
data class User(
    val id: String?,
    val email: String?,
    val firstName: String?,
    val lastName: String?,
    val phone: String?,
    val address: String?,
    val dob: String?,
    val customer: String?,
    val enterpriseIds: List<String>,
    val vendorIds: List<String>)
data class Enterprises(
    val id: String,
    val enterpriseName: String,
    val typeLabel: String,
    val country: String,
    val imageId: String,
    val managers: List<String>,
    val members: List<String>,
    val stripe: Boolean,
    val locations: List<String>)
data class Vendors(
    val id: String,
    val vendorName: String,
    val typeLabel: String?,
    val userRole: String,
    val latitude: Float,
    val longitude: Float,
    val partner: Boolean,
    val country: String?,
    val imageId: String,
    val stripe: Boolean)

首先,Kotlin 中没有安全的 null 类型。变量可为空或不可空。

如果 API 通过不存在或将其显式设置为 null 来提供 null 值,则数据类应以这些变量可为 null 的方式反映这一点(问号?紧跟在数据类型之后)。

将这些数据类映射到实体(域模型)的那一刻,您应该正确处理空情况。由于这是一个有效的情况,即 API 提供您期望的空值,因此您应该通过分配默认值来处理这种情况。

使用 elvis 运算符只是优雅地处理可为空类型的一种方法,但如果您使用它,仍然是您的选择。

如果你将所有属性声明为 nullable 这并不比 Java 好多少,即使您使用 null 安全运算符访问它们也是如此。如果您的 JSON 属性具有null值,这意味着在您的业务逻辑中它们并不总是具有值,并且您有责任通过回退到默认值(即 emptyList()""),或者可能更复杂的内容,例如重定向到登录屏幕。

相关内容

最新更新