Пользовательский кодек Tapir
Я застрял в каком-то месте, использую scala, tapir и circe.
sealed abstract class S1Error extends Product with Serializable
object S1Error {
final case class SError(error: SMError) extends S1Error
}
sealed abstract class SMError(message: String)
object SMError {
final case class SVError(message: String) extends SMError(message)
}
Для ошибки тапира, но я использую это
val schemaVersionError: EndpointOutput.StatusMapping[SError] = statusMappingValueMatcher(
StatusCode.BadRequest,
jsonBody[SError]
.description("XXXX.")
) {
case SMError(SVError(_)) => true
case _ => false
}
Теперь из-за этой структуры я получаю результат API
{
"error": {
"SVError": {
"message": "XXXXG"
}
}
}
где в идеале я хотел бы получить ответ как
"message": "XXXXG"
Не могу изменить структуру ошибки. Есть ли способ обернуть эту ошибку с помощью специального кодека, чтобы получить требуемый результат.
1 ответ
Кодек Tapir является производным от декодера и кодировщика Circe.
Вы видите способ кодирования классов case по умолчанию с помощью circe.
Circe предоставляет возможность кодировать классы случаев так, как вы описали с помощью deriveUnwrappedEncoder
от https://github.com/circe/circe-generic-extras. К сожалению, он не компилируется дляSMError
(вероятно, механизм деривации запутан вашей иерархией абстрактных классов).
Вы можете просто создать кодировщик вручную:
sealed abstract class S1Error extends Product with Serializable
object S1Error {
final case class SError(error: SMError) extends S1Error
implicit val encoder: Encoder[SError] = Encoder[SMError].contramap(_.error)
// or you can use deriveUnwrappedEncoder from circe-generic-extras:
// implicit val encoder: Encoder[SError] = deriveUnwrappedEncoder
}
//I also needed to make message a field in SMError
sealed abstract class SMError(val message: String)
object SMError {
final case class SVError(override val message: String) extends SMError(message)
implicit val encoder: Encoder[SMError] = Encoder.encodeJsonObject.contramap{s => JsonObject("message" -> s.message.asJson)}
}
Ответ теперь выглядит так:
{
message": "XXXXG"
}