将类映射在一起时处理类中的空类型的最佳实践

时间:2018-12-26 15:00:49

标签: kotlin

我正在使用Kotlin 1.30。我有以下将从API中填充的实体类。而且某些属性在API中可能为null,因此我已使用安全null类型声明了它们。

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

当我映射类时,我有两个想法。

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

在以下代码段中,我正在使用elvis运算符。只是想知道什么是最佳做法?

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填充的实体类,因此其中任何一个都可以为空

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)

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

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)

2 个答案:

答案 0 :(得分:2)

首先,Kotlin中没有安全的null类型。变量是否可以为空。

如果API通过不存在或通过将它们显式设置为null来传递空值,则您的数据类应以那些变量可为空的方式(在数据类型后紧跟问号?)反映这一点。 / p>

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

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

答案 1 :(得分:1)

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