Search code examples
jsonscalaspray-json

Scala spray-json type match


I am used to using sacla spray-json to serializate and deserializate json data. But there have one problem confuse me for a long time: Assume the json data is:

{"a":"123"}

but sometimes it may be:

{"a":123} or {"a":123.0}

Problem is that I don't konw the data type in advance, it may be String or Int or Doule.

When using spray-json framework, I need to determine the data format in advance. Below is my code:

case class Input(a:Either[String,Numeric[Either[Int,Doule]]])

object SelfJsonProtocol extends DefaultJsonProtocol {
    // format the json type into scala type.
    implicit val InputFormat = jsonFormat1(Input)
}

But that was wrong when compile it. Anyone can help me?


Solution

  • Actually, the Either type in your case class can be made to work if you simplify it a little. Use Either[Double, String]. This way Ints are automatically parsed as Doubles.

    Example:

    import spray.json._
    
    case class DoubleTest(a: Either[Double, String])
    
    object MyJsonProtocol extends DefaultJsonProtocol {
      implicit val doubleTestFormat = jsonFormat1(DoubleTest)
    }
    
    import MyJsonProtocol._
    
    val json = """[{"a":"123"}, {"a":123}, {"a":123.0}]"""
    val ast = JsonParser(json)
    val DTs = ast.convertTo[List[DoubleTest]]
    DTs.map { dt =>
      dt.a match {
        case Left(d) => { println("double found"); d }
        case Right(d) => { println("string found"); d.toDouble }
      }
    }
    

    Output:

    json: String = [{"a":"123"}, {"a":123}, {"a":123.0}]
    ast: spray.json.JsValue = [{"a":"123"},{"a":123},{"a":123.0}]
    DTs: List[DoubleTest] = List(DoubleTest(Right(123)), DoubleTest(Left(123.0)), DoubleTest(Left(123.0)))
    string found
    double found
    double found
    res35: List[Double] = List(123.0, 123.0, 123.0)