如何定义变量可能不存在于数据 class (JSON/Kotlin) 中?

How to define that a variable may not be present in data class (JSON/Kotlin)?

我在 Kotlin 中有一个数据 class 和一个对象:

一个数据classTranche.kt

@JsonIgnoreProperties(ignoreUnknown = true)
data class Tranche(
        @JsonProperty("id") var id: String,
        @JsonProperty("status") var status: String,
        @JsonProperty("instrumentType") var instrumentType: String,
        @JsonProperty("ssdRepaymentDetails") var ssdRepaymentDetails: RepaymentDetails?,
        @JsonProperty("loanRepaymentDetails") var loanRepaymentDetails: RepaymentDetails?
) : PayloadContent

还有一个 对象DummyTransaction.kt

val trancheDummy = Tranche(id = "0", name = "dummy", status = "DRAFT", instrumentType = "Loan", ssdRepaymentDetails = repaymentDetailsDummy, loanRepaymentDetails = repaymentDetailsDummy)

将 RepaymentDetails 设置为可为 null 我允许 ssdDetails 和 loanDetails 为 null。这很好,但我不需要 ssdDetails 和 loanDetails。如果 instrumentType 是 SSD,我需要 ssdDetails;如果 instrumentType 是 Loan,我需要 loanDetails。

如果不保留不同产品的两个数据 class,我该怎么做?意思是,我想拥有以下两个对象:

val trancheDummySsd = Tranche(id = "0", name = "dummy", status = "DRAFT", instrumentType = "SSD", ssdRepaymentDetails = repaymentDetailsDummy)
val trancheDummyLoan = Tranche(id = "0", name = "dummy", status = "DRAFT", instrumentType = "Loan", loanRepaymentDetails = repaymentDetailsDummy)

需要的原因是 JSON 字符串对于 SSD 和贷款是不同的,而在后端读取它时,我只需要该字符串中的一个属性 (payCycle),并且该属性两种产品通用。

RepaymentDetails.kt

@JsonIgnoreProperties(ignoreUnknown = true)
data class RepaymentDetails(
        @JsonProperty("payCycle") var payCycle: String?
)

这部分是用 Go 编写的,它定义了 JSON 结构:

type RepaymentDetails struct {
    PayCycle string `json:"payCycle,omitempty"` 
}

type LoanRepaymentDetails struct {
    RepaymentDetails // inherits RepaymentDetails struct 
}

type SsdRepaymentDetails struct {
    RepaymentDetails // inherits RepaymentDetails struct 
    LastPaymentDate string `json:"lastPaymentDate,omitempty"`
}

在我看来,最好的做法是使用 sealed class(为简洁起见删除了注释):

sealed class Tranche(var id: String, var status: String, var instrumentType: String) {
    data class SSDTranche(id: String, status: String, var ssdDetails: RepaymentDetails) : Tranche(id, status, "SSD")
    data class LoanTranche(id: String, status: String, var loanDetails: RepaymentDetails) : Tranche(id, status, "Loan")
}

但如果您真的不想使用两种不同的类型,您至少可以使用一个 init 块来验证您是否获得了正确的参数:

init {
    when (instrumentType) {
        "SSD" -> requireNotNull(ssdDetails)
        "Loan" -> requireNotNull(loanDetails)
    }
}

考虑到数据对象的 class 定义无论数据类型变量如何都不会改变,使用注释为 RepaymentDetails 类型的单个 "repaymentDetails" Json 属性@JsonAlias("ssdRepaymentDetails", "loanRepaymentDetails") 足以将任一可能的有效负载反序列化为单个不可为 null 的字段。

正如 OP 强调的那样,可能需要额外的 @JsonProperty("repaymentDetails")