我有以下案例课
case class DataResponse(results: Iterable[Array[Option[String]]], exceptionMessage: Option[String])
主要由于results
的类型,我似乎无法为此类编写Reads。如果我尝试没有选择。即Iterable[Array[String]]
可以工作,但是当json字符串具有空值时,它会崩溃。
implicit val DataReads2 = (
(JsPath \ “results”).read[Iterable[Array[Option[String]]]] and //compile error
(JsPath \ “exceptionMessage”).readNullable[String]
)(DataResponse.apply _)
编译错误:
No Json deserializer found for type Iterable[Array[Option[String]]]. Try to implement an implicit Reads or Format for this type.
如果我尝试实现隐式读取,则会得到:
implicit val itrOptReads = Json.reads[Iterable[Array[Option[String]]]]
No apply function found for scala.collection.Iterable
基本上,我似乎找不到更简单的方法来处理将json编组为Iterable[Array[Option[String]]]
的方法。应该有一个。
答案 0 :(得分:1)
在这种情况下,您可以实现CustomIterableFormat
。这是示例:
object CustomIterableFormat extends Reads[Iterable[Array[Option[String]]]] with Writes[Iterable[Array[Option[String]]]] {
implicit val optionalStringArrayFormat = CustomArrayFormat
override def reads(json: JsValue): JsResult[Iterable[Array[Option[String]]]] = {
Try(json.as[Iterable[JsValue]].map { someJson =>
someJson.as[Array[Option[String]]]
}).map(JsSuccess(_)).getOrElse(JsError(s"invalid sequence: $json"))
}
override def writes(o: Iterable[Array[Option[String]]]): JsValue = {
Json.toJson(o)
}
}
object CustomArrayFormat extends Reads[Array[Option[String]]] with Writes[Array[Option[String]]] {
override def reads(json: JsValue): JsResult[Array[Option[String]]] = {
Try(json.as[Array[JsValue]].map {
case JsNull => None
case JsString(value) => Some(value)
}).map(JsSuccess(_)).getOrElse(JsError(s"invalid sequence: $json"))
}
override def writes(o: Array[Option[String]]): JsValue = {
Json.toJson(o)
}
}
然后将CustomIterableFormat导入您的伴随对象中
case class DataResponse(results: Iterable[Array[Option[String]]], exceptionMessage: Option[String])
object DataResponse {
implicit val resultsFormat = CustomIterableFormat
implicit val DataReads2 = (
(JsPath \ "results").read[Iterable[Array[Option[String]]]] and
(JsPath \ "exceptionMessage").readNullable[String]
)(DataResponse.apply _)
}
这是一个简单的工作示例:
object TestDataResponseParsing {
def main(args: Array[String]): Unit = {
val jsonStr = """{"results":[[null,"testing"]],"exceptionMessage":null}"""
val parsedFromJson = Json.parse(jsonStr).as[DataResponse]
println(parsedFromJson)
}
}
希望这会有所帮助!
答案 1 :(得分:1)
Circe是Scala中最受欢迎的JSON解析库之一
这是使用Circe的更优雅的解决方案。
import io.circe.generic.auto._
import io.circe.parser
case class DataResponse(results: Iterable[Array[Option[String]]], exceptionMessage: Option[String])
object DataResponseParsing extends App {
val jsonStr = """{
"results" : [
[
null,
"bar-1"
],
[
"foo-2",
"bar-2"
]
],
"exceptionMessage" : null
}""".stripMargin
val result = parser.decode[DataResponse](jsonStr)
val dataResponse = result match {
case Right(value) => value
case Left(error) => throw error
}
println(dataResponse)
}
Circe's automatic derivation非常精通,它会自动编码/解码几乎所有类型的Scala对象。因此,我们无需在任何地方定义隐式。只需在您的Scala类中导入io.circe.generic.auto._
即可。
希望这会有所帮助!