Search code examples
scalaplay-json

JSON quotes make parsing impossible


I'm using play's json libraries to parse json sent to me by javascript. Everything worked fine during initial testing but I have discovered that the various front ends send json values bare or wrapped in quotes. This can change from time to time so my parsing fails as what looks like a float one data looks like a string the next.

I'm using implicit Reads to parse to a model and really want to continue to do that. Currently I have:

case class dsource (
                     A: String,
                     B: Int,
                     C: Float,
                     D: Float,
                     E: Float,
                     F: Float,
                     G: Float
                   )

object dsource {
  implicit val dsourceaReads: Reads[dsource] = (
    (JsPath \ "A").read[String] and
      (JsPath \ "B").read[String].map(_.toInt) and
      (JsPath \ "C").read[String].map(_.toFloat) and
      (JsPath \ "D").read[String].map(_.toFloat) and
      (JsPath \ "E").read[Float] and
      (JsPath \ "F").read[Float] and
      (JsPath \ "G").read[Float]
  ) (dsource.apply _)
}}

I want to avoid preprocessing the Json and I can't control what the front end sends me, I need to handle the value wether it is encased in quotes or not. I guess this is the challenge with having a weakly typed front end sending to a strongly typed back end.

Any suggestions?

Thanks in advance.


Solution

  • You could create helpers:

    val maybeQuotedInt: Reads[Int] = Reads { 
      js => js.validate[String].map(_.toInt).orElse(js.validate[Int])
    }
    // similar for Float/Double/etc
    

    and then use them as

    (JsPath \ "A").read[String] and
      (JsPath \ "B").read(maybeQuotedInt) and
      (JsPath \ "C").read(maybeQuotedFloat) and ...
    

    This is untested, just going from the documentation, so might need some changes but this approach should work.