Skip to content

Instantly share code, notes, and snippets.

@megri
Last active March 15, 2018 08:36
Show Gist options
  • Save megri/7a4be59cc619614ed3063a190243a7b2 to your computer and use it in GitHub Desktop.
Save megri/7a4be59cc619614ed3063a190243a7b2 to your computer and use it in GitHub Desktop.
import cats.syntax.apply._
import io.circe._
import io.circe.literal._
object JsonValidation{
def validate[A: Decoder]( f: HCursor => ACursor, pred: A => Boolean, err: A => String ): Decoder[A] =
Decoder.instance(
f andThen{ ac =>
ac.as[A].flatMap( a =>
if ( pred( a ) )
Right( a )
else
Left( DecodingFailure( err( a ), ac.history ) ) )
}
)
}
implicit val someRequestDecoder: Decoder[SomeRequest] ={
def stringOfLength( min: Int, max: Int )( f: HCursor => ACursor ): Decoder[String] =
JsonValidation.validate[String]( f, s => s.length >= min && s.length <= max,
s => s"Length must be between $min and $max; was ${s.length}" )
val name = stringOfLength( 1, 10 )( _.downField( "name" ) )
val desc = stringOfLength( 0, 20 )( _.downField( "description" ) )
( name, desc ).mapN( SomeRequest )
}
case class SomeRequest( name: String, description: String )
val name = "A name too long"
val desc = "this description is longer than 20 characters"
val json = json"""{ "name": $name, "description": $desc }"""
Decoder[SomeRequest].accumulating.apply( json.hcursor )
@voidcontext
Copy link

Ok, I think I understand what was the confusion (at least from my perspective): my code is attaching the validation of the individual fields to the containing JSON element. The accumulation is not working as apparently 1 element can only have 1 error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment