【发布时间】:2020-07-06 14:32:20
【问题描述】:
我有一个 Scala 项目,我在其中使用 Circe 来处理 json。 我无法从 JSON 解码到层次结构的子类。
我遇到问题的代码是以下测试:
test("FailingResponse - Conversion between case object and Json works") {
val caseObject = FailingResponse("Some Error", StatusCodes.INTERNAL_ERROR)
val jsonString = caseObject
.asJson
.printWith(Printer.noSpaces)
decode[ValuationResponse](jsonString) must be(Right(caseObject))
}
我希望能够解码为 ValuationResponse 的任何子类,因为在解码时我无法确定响应是失败响应还是成功响应。我希望解码器能够推断出它是什么类型的 ValuationReponse,对其进行解码并使其作为“通用”ValuationResponse 可用。然后我可以使用匹配案例或类似的东西来操作它以获得实际的特定类型。
相反,我在该测试中得到的是 DecodingFailure 错误。我做错了什么?
这是层次结构的代码:
sealed trait ValuationResponse {
def statusCode: StatusCode
}
case class SuccessfulResponse(values: List[StockValuation], symbol: String, function: TimeSeriesType, statusCode: StatusCode) extends ValuationResponse
case class FailingResponse(reason: String, statusCode: StatusCode) extends ValuationResponse
case class ValuationRequest(function: TimeSeriesType = TIME_SERIES_INTRADAY, symbol: String, interval: IntraDayInterval = IntraDayIntervals.MIN_5)
object derivation {
implicit val encodeResponse: Encoder[ValuationResponse] = Encoder.instance {
case response@SuccessfulResponse(_, _, _, _) => response.asJson
case response@FailingResponse(_, _) => response.asJson
}
implicit val decodeResponse: Decoder[ValuationResponse] =
List[Decoder[ValuationResponse]](
Decoder[SuccessfulResponse].widen,
Decoder[FailingResponse].widen
).reduceLeft(_ or _)
implicit val encodeRequest: Encoder[ValuationRequest] = Encoder.instance {
case response@ValuationRequest(_, _, _) => response.asJson
}
implicit val decodeRequest: Decoder[ValuationRequest] =
List[Decoder[ValuationRequest]](
Decoder[ValuationRequest].widen
).reduceLeft(_ or _)
}
这些是它使用的枚举(是的,我知道有一个状态码的枚举是愚蠢的啊):
sealed abstract class TimeSeriesType(val text: String) extends EnumEntry {}
sealed abstract class IntraDayInterval(val text: String) extends EnumEntry {}
object TimeSeriesFunctions extends Enum[TimeSeriesType] with CirceEnum[TimeSeriesType] {
val values: immutable.IndexedSeq[TimeSeriesType] = findValues
case object TIME_SERIES_INTRADAY extends TimeSeriesType("TIME_SERIES_INTRADAY")
case object TIME_SERIES_DAILY extends TimeSeriesType("TIME_SERIES_DAILY")
case object TIME_SERIES_WEEKLY extends TimeSeriesType("TIME_SERIES_WEEKLY")
case object TIME_SERIES_MONTHLY extends TimeSeriesType("TIME_SERIES_MONTHLY")
}
object IntraDayIntervals extends Enum[IntraDayInterval] with CirceEnum[IntraDayInterval] {
val values: immutable.IndexedSeq[IntraDayInterval] = findValues
case object MIN_1 extends IntraDayInterval("1min")
case object MIN_5 extends IntraDayInterval("5min")
case object MIN_15 extends IntraDayInterval("15min")
case object MIN_30 extends IntraDayInterval("30min")
case object MIN_60 extends IntraDayInterval("60min")
}
object StatusCodes extends Enum[StatusCode] with CirceEnum[StatusCode] {
val values: immutable.IndexedSeq[StatusCode] = findValues
case object SUCCESS extends StatusCode(200)
case object INTERNAL_ERROR extends StatusCode(500)
case object REQUESTER_ERROR extends StatusCode(400)
}
【问题讨论】:
标签: json scala enums traits circe