我正在开发的应用程序必须从数据源解码json,对于给定字段,该数据源可能返回List [String]或List [Double]。我想将此json解码为case类,以便我可以处理数据。
[{
"id": 123,
"latlng": ["-12.777", "18.776"]
}, {
"id": 123,
"latlng": [-12.777, 18.776]
}]
Im使用大约0.11.1
目前我的案例类看起来像
case class Report(id:Int, latlng:Either[List[String],List[Double]])
和我的解码代码
decode[List[Report]](testData)
我收到错误
DecodingFailure at [0].latlng: [A, B]Either[A, B]
答案 0 :(得分:1)
听起来您已经有了适合您的解决方案。我找到了解决您原始问题的方法。它不是很优雅,但是可以工作。也许有一个更优雅的解决方案,涉及到Cats库中的Validated monad,但是我对Cats库并不十分熟悉,无法以这种方式编写它。
import io.circe._
import io.circe.parser._
object Main {
def main(args: Array[String]) = {
val testData =
"""
|[{
| "id": 123,
| "latling": ["-12.777", "18.776"]
|}, {
| "id": 123,
| "latling": [-12.777, 18.776]
|}]
""".stripMargin
println(decode[List[Report]](testData))
}
case class Report(id: Int, latling: Either[List[String],List[Double]])
object Report {
implicit val reportDecoder: Decoder[Report] = new Decoder[Report] {
override def apply(c: HCursor): Decoder.Result[Report] = {
val stringAttempt = for {
id <- c.downField("id").as[Int]
latlingString <- c.downField("latling").as[List[String]]
} yield Report(id, Left(latlingString))
val doubleAttempt = for {
id <- c.downField("id").as[Int]
latlingDouble <- c.downField("latling").as[List[Double]]
} yield Report(id, Right(latlingDouble))
stringAttempt match {
case Right(stringValue) => Right(stringValue)
case Left(stringFailure) => doubleAttempt
}
}
}
}
}
您可以通过
启动sbt来运行sbt
并运行
runMain Main
这是我的build.sbt文件:
name := "stackoverflow20190821"
version := "0.1"
scalaVersion := "2.12.0"
val circeVersion = "0.11.1"
libraryDependencies ++= Seq(
"io.circe" %% "circe-core",
"io.circe" %% "circe-generic",
"io.circe" %% "circe-parser"
).map(_ % circeVersion)