Steve Gailey
Steve Gailey

Reputation: 128

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.

Upvotes: 1

Views: 55

Answers (1)

Alexey Romanov
Alexey Romanov

Reputation: 170723

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.

Upvotes: 1

Related Questions