Я хочу, чтобы декодировать следующую 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% процессора на обработку JSON, и это просто не выглядит правильным. Либо это плохой дизайн ADT, либо в Circe должен быть способ справиться с этим лучше. Есть идеи?
Да, я подумал о том, чтобы вернуться прямо к 'CreditCard' из' PaymentType'. Моя первоначальная реакция заключалась не в том, чтобы сделать это, потому что он делает родительский класс осведомленным о своих детях, что не является хорошей практикой. Но поскольку это все запечатанные типы, это, вероятно, не так уж плохо. И это, безусловно, лучше, чем в настоящее время альтернатива. – Haspemulator
@ Haspemulator Да, поскольку вы уже застряли с '.or (CreditCard.decoder)' Я не вижу большой разницы между ними в этом отношении. –
Правильно, то, что я уже разместил, содержало такую обратную связь в любом случае. Тем не менее до этого у меня не было резервной копии вообще, и она просто потерпела неудачу во время выполнения с 'MatchError', когда были встречены некоторые строки' CreditCard'. – Haspemulator