spary-json parseJson func的故障安全包装器

时间:2015-06-03 09:05:30

标签: scala spray-json

我想为spary-json str.parseJson.convertTo[A]编写故障安全包装器。 它必须有逻辑 - "当我不能将json解析为案例类A时,我会尝试将其解析为案例类Error"

def parse(str:String) = 
   try {
     str.parseJson.convertTo[A]
   } catch {
     case e:Exception => str.parseJson.convertTo[Error]
   }

但我也希望将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]

                         ^

如何修复此错误? 我可以通过其他方式做到这一点吗?

1 个答案:

答案 0 :(得分:1)

简化事情,看起来就像你一样:

  • 使用适当的JsonReaders
  • 定义了3个案例类
  • 定义了一个泛型函数,其类型为 lower 绑定到Obj。

编译器告诉你它找不到实现trait Obj所有可能的类的JsonReader,因为你只为Error,DataA和DataB定义了特定的JsonReader。

要解决此问题,您可以使用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
  }