A simple and easy validation syntax for Scala and Java classes
For more detailed information, please refer to the API Documentation.
Requires: Scala 2.12, 2.11
- Add it to your project
- Basic Usage
- Nested Classes
- Validating With
- Reporting an Issue
- Contributing
- License
Using sbt:
In build.sbt
:
libraryDependencies += "com.github.vickumar1981" %% "svalidate" % "1.0.1"
Using gradle:
In build.gradle
:
dependencies {
compile 'com.github.vickumar1981:svalidate_2.12:1.0.1'
}
Using Maven:
In pom.xml
:
<dependency>
<groupId>com.github.vickumar1981</groupId>
<artifactId>svalidate_2.12</artifactId>
<version>1.0.1</version>
</dependency>
Note: For Java 7 or Scala 2.11, please use the svalidate_2.11
artifact as a dependency instead.
Let's create a simple class called Address
that looks like:
package test.example
case class Address(street: String,
city: String,
state: String,
zipCode: String)
The rules for validating an Address
are:
- street address is required
- city is required
- state abbr. must be exactly two capital letters
- zip code must be exactly 5 digits
Using sValidate
's validation syntax, we can add a new validator of the type Validatable<Address>
package test.example
import com.github.vickumar1981.svalidate.{Validatable, Validation}
object ModelValidations {
implicit object AddressValidator extends Validatable[Address] {
override def validate(value: Address): Validation = {
(value.street.nonEmpty orElse "Street addr. is required") ++
(value.city.nonEmpty orElse "City is required") ++
(value.zipCode.matches("\\d{5}") orElse "Zip code must be 5 digits") ++
(value.state.matches("[A-Z]{2}") orElse "State abbr must be 2 letters")
}
}
}
To extend validation to the Address
class, we import our validator and the validation syntax.
import test.example.Address
object TestValidation {
import test.example.ModelValidations._
import com.github.vickumar1981.svalidate.ValidationSyntax._
def main(args: Array[String]): Unit = {
val addr = Address("", "", "", "")
val errors = addr.validate().errors
println(errors)
// ArrayBuffer(Street addr. is required, City is required, Zip code must be 5 digits, State abbr must be 2 letters)
}
}
See Scala Address validation example
See Java Address validation example
Let's say we have a Person
class which contains an Address
instance,
and whose validation depends upon the validation of the address
member instance.
Additionally, a Person
also has a hasContact: Boolean
indicator
The class might look like:
case class Person(firstName: String,
lastName: String,
hasContactInfo: Boolean,
address: Option[Address] = None,
phone: Option[String] = None)
The rules for validating a Person
are:
- first name is required
- last name is required
- phone number and address are both optional, and their
validation depends upon the
hasContactInfo
indicator - a phone number must be exactly 10 numbers
- if the
hasContactInfo
flag is true, then bothphone
andaddress
should be validated - if the
hasContactInfo
flag is false, then bothphone
andaddress
should be empty
An example validator for Person
might look like:
package text.example
import com.github.vickumar1981.svalidate.{Validatable, Validation}
object ModelValidations {
implicit object PersonValidator extends Validatable[Person] {
def validateContactInfo(value: Person): Validation = {
(value.address errorIfEmpty "Address is required") ++
(value.phone errorIfEmpty "Phone # is required") ++
value.address.maybeValidate() ++
value.phone.maybeValidate(_.matches("\\d{10}") orElse "Phone # must be 10 digits")
}
override def validate(value: Person): Validation = {
(value.firstName.nonEmpty orElse "First name is required") ++
(value.lastName.nonEmpty orElse "Last name is required") ++
(value.hasContactInfo andThen validateContactInfo(value)) ++
value.hasContactInfo.orElse {
(value.address errorIfDefined "Address must be empty") ++
(value.phone errorIfDefined "Phone # must be empty")
}
}
}
}
See Scala Person validation example
See Java Person validation example
Sometimes, validation depends on an external value. This is where we can use the .validateWith[T](t: T)
syntax.
Let's say we have a Contacts
class which contains an optional list of Facebook and Twitter emails.
Each user in our system also has a ContactSettings
object, that determines the validation of the user's Contacts
The two classes might look like:
case class Contacts(facebook: Option[List[String]] = None, twitter: Option[List[String]] = None)
case class ContactSettings(hasFacebookContacts: Option[Boolean] = Some(true),
hasTwitterContacts: Option[Boolean] = Some(true))
The rules for validating a user's Contacts
are:
- If the
hasFacebookContacts
orhasTwitterContacts
indicators are set totrue
, then the respectivefacebook
ortwitter
list of emails for a user must be supplied - If the
hasFacebookContacts
orhasTwitterContacts
indicators are set tofalse
, then the respectivefacebook
ortwitter
list of emails for a user must be empty - If the
hasFacebookContacts
orhasTwitterContacts
indicators are empty, then the respectivefacebook
ortwitter
list of emails can be empty or supplied
We will use a ValidatableWith[Contacts, ContactSettings]
validator.
An example implementation might look like:
package text.example
import com.github.vickumar1981.svalidate.{ValidatableWith, Validation}
object ModelValidations {
implicit object ContactInfoValidator extends ValidatableWith[Contacts, ContactSettings] {
override def validateWith(value: Contacts, contactSettings: ContactSettings): Validation = {
contactSettings.hasFacebookContacts.maybeValidate {
contacts =>
(contacts andThen { value.facebook errorIfEmpty "Facebook contacts are required" }) ++
(contacts orElse { value.facebook errorIfDefined "Facebook contacts must be empty"})
} ++
contactSettings.hasTwitterContacts.maybeValidate {
contacts =>
(contacts andThen { value.twitter errorIfEmpty "Twitter contacts are required" }) ++
(contacts orElse { value.twitter errorIfDefined "Twitter contacts must be empty" })
}
}
}
}
An example of using .validateWith
:
import test.example.{ContactSettings, ContactInfo}
object TestValidation {
import test.example.ModelValidations._
import com.github.vickumar1981.svalidate.ValidationSyntax._
def main(args: Array[String]): Unit = {
val contacts = Contacts(None, None)
val contactSettings = ContactSettings(None, None)
val result = contact.validateWith(contactSettings)
println(result.isSuccess)
// true
}
}
See Scala Contacts validation example
Note: There is currently no .validateWith
syntax for Java
Please report any issues or bugs to the Github issues page.
Please view the contributing guidelines
This project is licensed under the Apache 2 License.