spray-json parseJson 函数的故障安全包装器
Fail-safe wrapper for spary-json parseJson func
我想为 spary-jsonstr.parseJson.convertTo[A]
编写故障安全包装器。
它必须有逻辑 - "when I can't parse json as case class A
, I try parse it as case class Error
"
def parse(str:String) =
try {
str.parseJson.convertTo[A]
} catch {
case e:Exception => str.parseJson.convertTo[Error]
}
但我也想将 class A
作为参数。
def parse[A<:Obj](str:String):Obj = {
import JsonProtocols._
try {
str.parseJson.convertTo[A]
} catch {
case e:Exception => str.parseJson.convertTo[Error]
}
}
使用:
...
trait Obj
case class Error(error:String) extends Obj
case class DataA(a1:String, a2: Int) extends Obj
case class DataB(b1:String, b2: Boolean) extends Obj
object JsonProtocols extends DefaultJsonProtocol {
implicit val errorFormat = jsonFormat1(Error)
implicit val dataAFormat = jsonFormat2(DataA)
implicit val dataBFormat = jsonFormat2(DataB)
...
}
...
parse[DataA]("...json...") match {
case obj: DataA => "..."
case obj: Error => "..."
}
...
我遇到编译错误:
Error:(25, 30) Cannot find JsonReader or JsonFormat type class for A
str.parseJson.convertTo[A]
^
我该如何解决这个错误?
我可以用其他方式做到这一点吗?
简化事情,看起来你已经:
- 使用适当的 JsonReaders
定义了 3 个案例 类
- 定义了一个泛型函数,其类型 lower 绑定到 Obj。
编译器告诉您它无法为 all possible 类 implementing trait Obj
找到 JsonReader,因为您只为 Error 定义了特定的 JsonReader , DataA 和 DataB.
要解决此问题,您可以使用 Either[T,Error]
类型进行反序列化,例如:
sealed trait Obj
case class Error(error:String) extends Obj
case class DataA(a1:String, a2: Int) extends Obj
case class DataB(b1:String, b2: Boolean) extends Obj
val strA = """{"a1":"foo", "a2": 1}"""
val strB = """{"b1":"bar", "b2": false}"""
val srtE = """{"error": "oops"}"""
object JsonProtocols extends DefaultJsonProtocol {
implicit val errorFormat = jsonFormat1(Error)
implicit val dataAFormat = jsonFormat2(DataA)
implicit val dataBFormat = jsonFormat2(DataB)
}
import JsonProtocols._
val result:Obj = strA.parseJson.convertTo[Either[DataA,Error]] match {
case Left(dataA) => dataA
case Right(error) => error
}
我想为 spary-jsonstr.parseJson.convertTo[A]
编写故障安全包装器。
它必须有逻辑 - "when I can't parse json as case class A
, I try parse it as case class Error
"
def parse(str:String) =
try {
str.parseJson.convertTo[A]
} catch {
case e:Exception => str.parseJson.convertTo[Error]
}
但我也想将 class A
作为参数。
def parse[A<:Obj](str:String):Obj = {
import JsonProtocols._
try {
str.parseJson.convertTo[A]
} catch {
case e:Exception => str.parseJson.convertTo[Error]
}
}
使用:
...
trait Obj
case class Error(error:String) extends Obj
case class DataA(a1:String, a2: Int) extends Obj
case class DataB(b1:String, b2: Boolean) extends Obj
object JsonProtocols extends DefaultJsonProtocol {
implicit val errorFormat = jsonFormat1(Error)
implicit val dataAFormat = jsonFormat2(DataA)
implicit val dataBFormat = jsonFormat2(DataB)
...
}
...
parse[DataA]("...json...") match {
case obj: DataA => "..."
case obj: Error => "..."
}
...
我遇到编译错误:
Error:(25, 30) Cannot find JsonReader or JsonFormat type class for A
str.parseJson.convertTo[A]
^
我该如何解决这个错误? 我可以用其他方式做到这一点吗?
简化事情,看起来你已经:
- 使用适当的 JsonReaders 定义了 3 个案例 类
- 定义了一个泛型函数,其类型 lower 绑定到 Obj。
编译器告诉您它无法为 all possible 类 implementing trait Obj
找到 JsonReader,因为您只为 Error 定义了特定的 JsonReader , DataA 和 DataB.
要解决此问题,您可以使用 Either[T,Error]
类型进行反序列化,例如:
sealed trait Obj
case class Error(error:String) extends Obj
case class DataA(a1:String, a2: Int) extends Obj
case class DataB(b1:String, b2: Boolean) extends Obj
val strA = """{"a1":"foo", "a2": 1}"""
val strB = """{"b1":"bar", "b2": false}"""
val srtE = """{"error": "oops"}"""
object JsonProtocols extends DefaultJsonProtocol {
implicit val errorFormat = jsonFormat1(Error)
implicit val dataAFormat = jsonFormat2(DataA)
implicit val dataBFormat = jsonFormat2(DataB)
}
import JsonProtocols._
val result:Obj = strA.parseJson.convertTo[Either[DataA,Error]] match {
case Left(dataA) => dataA
case Right(error) => error
}