Как определить, что переменная может отсутствовать в классе данных (JSON / Kotlin)? - PullRequest
0 голосов
/ 23 февраля 2020

У меня есть класс данных и объект в Kotlin:

A класс данных Tranche.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 значения nullable Я допускаю, чтобы значения ssdDetails и loanDetails были равны нулю. Это все хорошо, но мне не нужны и ssdDetails, и loanDetails. Мне нужен ssdDetails в случае, если toolType - SSD, и loanDetails в случае, когда instrumentType - Loan.

Как мне это сделать, не сохраняя два класса данных для разных продуктов? Это означает, что я хотел бы иметь следующие два объекта:

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 и Loan, в то время как в бэкэнде, где его читают, я нужен только один атрибут (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"`
}

Ответы [ 2 ]

2 голосов
/ 23 февраля 2020

Учитывая, что определение класса объекта данных не изменяется независимо от переменной типа данных, использование одного атрибута "repaymentDetails" Json типа RepaymentDetails с аннотацией @JsonAlias("ssdRepaymentDetails", "loanRepaymentDetails") будет достаточно для десериализации любого из возможных полезные данные в одно, не допускающее обнуление поле.

Как подчеркивает OP, может потребоваться дополнительная @JsonProperty("repaymentDetails").

0 голосов
/ 23 февраля 2020

На мой взгляд, лучше всего использовать 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)
    }
}
...