我想用 Circe 解码以下 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
}
如您所见,有一个 parent 类型PaymentType
,它有一些直接继承者和另一个密封 trait family 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 应该有办法更好地处理这个问题。有任何想法吗?