Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala play json combinators for validating equality

I'm using play 2.2.0 Reads for validating incoming request in my application.

I'm trying to implement a very simple thing with json API. I have a json like this:

{
  "field1": "some value",
  "field2": "some another value"
}

I already have Reads that checks for other stuff like minimal length

case class SomeObject(field1: String, field2: String)
implicit val someObjectReads = (
  (__ \ "field1").read(minLength[String](3)) ~
  (__ \ "field2").read(minLength[String](3))
)(SomeObject)

I want to create a parser combinator that will match values of two fields and return JsSuccess if values are equal and otherwise JsError and combine it with existing Reads.

How can I achieve this?

UPDATE: clarified the question and changed the code.

like image 689
Andrey Neverov Avatar asked Feb 15 '23 04:02

Andrey Neverov


1 Answers

You can use filter to do further validation on parsed values:

import play.api.data.validation._
import play.api.libs.json._
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._

case class SomeObject(field1: String, field2: String)
implicit val someObjectReads = (
  (__ \ "field1").read(minLength[String](3)) ~
  (__ \ "field2").read(minLength[String](3))
)(SomeObject).filter(
  ValidationError("field1 and field2 must be equal")
) { someObject =>
  someObject.field1 == someObject.field2
}

If you want the error message to be listed against each field, then you'll have to use flatMap, eg:

implicit val someObjectReads = (
  (__ \ "field1").read(minLength[String](3)) ~
  (__ \ "field2").read(minLength[String](3))
)(SomeObject).flatMap { someObject =>
  Reads { _ =>
    if (someObject.field1 == someObject.field2) {
      JsSuccess(someObject)
    } else {
      JsError(Seq(
        JsPath("field1") -> Seq(ValidationError("field1 and field2 must be equal")),
        JsPath("field2") -> Seq(ValidationError("field1 and field2 must be equal"))
      ))
    }
  }
}
like image 86
James Roper Avatar answered Feb 28 '23 04:02

James Roper