将带有空字段的对象转换为带有不可空字段的对象或null

我有一个API返回的对象,具有不同的可空字段。 我想创建一个不可为空的字段的另一个对象,如果不可能的话返回null。 最适合这种情况的语言习语是什么? 目前我正在使用?.let {} ,它看起来很丑陋:

 fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson, correctAnswerText: String): AnswerResponseUi? { return userAnswer.id?.let { userAnswerId -> userAnswer.text?.let { userAnswerText -> answerResponse.answer?.id?.let { correctAnswerId -> answerResponse.points?.let { points -> answerResponse.discount?.let { discount -> answerResponse.booster?.let { booster -> return AnswerResponseUi(userAnswerId, correctAnswerId, userAnswerText, correctAnswerText, points, discount, booster.name ?: "") } } } } } } } 

如果您的类AnswerGsonAnswerResponseGson将其属性声明为val ,那么可以将您的代码转换为如下所示的代码:

 fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson, correctAnswerText: String): AnswerResponseUi? { if (userAnswer.id == null || userAnswer.text == null || answerResponse.discount == null || answerResponse.points == null || answerResponse.booster == null || answerResponse.answer == null || answerResponse.answer.id == null ) return null return AnswerResponseUi(userAnswer.id, answerResponse.answer.id, userAnswer.text, correctAnswerText, answerResponse.points, answerResponse.discount, answerResponse.booster.name ?: "") } 

这个例子使用智能转换 :编译器分析控制流程,并证明如果最后一条语句到达,那么上面检查的值都不为null

这些检查不适用于安全的解除链接,我必须先检查answerResponse.answer ,然后answerResponse.answer.id


如果您有var属性,则不能应用智能强制转换,因为该值在检查后可能会更改。

在这种情况下,仍然可以通过将值提取到局部变量并同时检查它们来减少代码中的嵌套:

 fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson, correctAnswerText: String): AnswerResponseUi? { val answerId = userAnswer.id ?: return null val correctAnswerId = answerResponse.answer?.id ?: return null val userAnswerText = userAnswer.text ?: return null val points = answerResponse.points ?: return null val discount = answerResponse.discount ?: return null val booster = answerResponse.booster ?: return null return AnswerResponseUi(answerId, correctAnswerId, userAnswerText, correctAnswerText, points, discount, booster.name ?: "") } 

而且,正如@ mfulton26注意到的,你甚至可以内联这些变量(也适用于vals ):

 fun convertAnswer(userAnswer: AnswerGson, answerResponse: AnswerResponseGson, correctAnswerText: String): AnswerResponseUi? { return AnswerResponseUi(userAnswer.id ?: return null, answerResponse.answer?.id ?: return null, userAnswer.text ?: return null, correctAnswerText, answerResponse.points ?: return null, answerResponse.discount ?: return null, (answerResponse.booster ?: return null).name ?: "") }