4
我想解碼與瑟茜以下ADT:瑟茜:解碼多層次的ADT有效
sealed trait PaymentType
object PaymentType extends EnumEncoder[PaymentType] {
case object DebitCard extends PaymentType
case object Check extends PaymentType
case object Cash extends PaymentType
case object Mobile extends PaymentType
}
sealed trait CreditCard extends PaymentType
object CreditCard extends EnumEncoder[CreditCard] {
case object UNKNOWN_CREDIT_CARD extends CreditCard
case object NOT_ACCEPTED extends CreditCard
case object VISA extends CreditCard
case object MASTER_CARD extends CreditCard
case object DINERS_CLUB extends CreditCard
case object AMERICAN_EXPRESS extends CreditCard
case object DISCOVER_CARD extends CreditCard
}
正如你可以看到,有一個父類PaymentType
,其中有一些直接的傳承者和另一個密封特質家庭CreditCard
。現在,解碼像這樣做:
object CreditCard {
implicit val decoder: Decoder[CreditCard] = Decoder.instance[CreditCard] {
_.as[String].map {
case "NOT_ACCEPTED" => NOT_ACCEPTED
case "VISA" => VISA
case "MASTER_CARD" => MASTER_CARD
case "DINERS_CLUB" => DINERS_CLUB
case "AMERICAN_EXPRESS" => AMERICAN_EXPRESS
case "DISCOVER_CARD" => DISCOVER_CARD
case _ => UNKNOWN_CREDIT_CARD
}
}
object PaymentType {
implicit val decoder: Decoder[PaymentType] = Decoder.instance[PaymentType] {
_.as[String].flatMap {
case "DebitCard" => Right(DebitCard)
case "Check" => Right(Check)
case "Cash" => Right(Cash)
case "Mobile" => Right(Mobile)
case _ => Left(DecodingFailure("", List()))
}
}.or(CreditCard.decoder.widen)
}
我不喜歡的是PaymentType
解碼器,特別是事實,我需要在完全正常的情況下創造的DecodingFailure
額外和不必要的情況下,當人們遇到信用卡 - 基於付款方式。我們已經將99.9%的CPU用於JSON處理,而且看起來不正確。要麼ADT設計不好,要麼Circe更好地處理這個問題。有任何想法嗎?
是的,我想直接從'PaymentType'回落到'CreditCard'。我最初的反應不是這樣做,因爲它讓父母階層意識到他們的孩子,這不是好習慣。但是因爲它們都是密封類型,所以可能並不是那麼糟糕。它當然比當前使用的替代方案更好。 – Haspemulator
@Haspemulator是的,因爲你已經被'.or(CreditCard.decoder)'卡住了''在這方面我沒有看到兩者之間的巨大差異。 –
沒錯,我已經發布了這樣的反向耦合。然而在此之前,我根本沒有後備功能,而且在遇到一些'CreditCard'字符串時,它在運行時失敗了'MatchError'。 – Haspemulator