Overview

Accord is a data validation library written in and for Scala. Compared to JSR 303 and Scalaz validation it aims to provide the following:

  • Composable: Because JSR 303 is annotation based, validation rules cannot be composed (annotations cannot receive other annotations as parameters). This is a real problem with some Scala features, for example Options or collections. Accord’s validation rules are trivially composable.
  • Simple: Accord provides a dead-simple story for validation rule definition by leveraging macros, as well as the validation call site (see example below).
  • Self-contained: Accord is macro-based but completely self-contained, and consequently only relies on the Scala runtime and reflection libraries.
  • Integrated: Other than providing its own DSL and matcher library, Accord is designed to easily integrate with the larger Scala ecosystem, and provides out-of-the-box support for Scala.js, as well as integration modules for Spring Validation, Specs2 and ScalaTest.

Accord is developed and used at Wix.com and distributed under the Apache License, Version 2.0, which basically means you can use and modify it freely. Feedback, bug reports and improvements are welcome!

By Example

:point_right:   See the DSL user guide for the full set of features.
:point_right:   See the API user guide for details of how descriptions are generated and used.

Defining a validator is quite straightforward:

import com.wix.accord.dsl._    // Import the validator DSL

case class Person( firstName: String, lastName: String )
case class Classroom( teacher: Person, students: Seq[ Person ] )

implicit val personValidator = validator[ Person ] { p =>
  p.firstName is notEmpty                   // The expression being validated is resolved automatically, see below
  p.lastName as "last name" is notEmpty     // You can also explicitly describe the expression being validated
}

implicit val classValidator = validator[ Classroom ] { c =>
  c.teacher is valid        // Implicitly relies on personValidator!
  c.students.each is valid
  c.students have size > 0
}

Executing the validator is equally straightforwad:

// Import the library
import com.wix.accord._

// Validate an object successfully
val validPerson = Person( "Wernher", "von Braun" )
val result: com.wix.accord.Result = validate( validPerson )   // Validator is implicitly resolved
assert( result == Success )

// Or get a detailed failure back:
val invalidPerson = Person( "", "No First Name" )
val failure: com.wix.accord.Result = validate( invalidPerson )
assert( failure == Failure( Set(                          // One or more violations
  RuleViolation(                                          // A violation includes:
    value = "",                                           //   - The invalid value
    constraint = "must not be empty",                     //   - The constraint being violated
    path = Path( Generic( "firstName" ) )                 //   - A path to the violating property
  )
) ) )

Getting Started

:point_right:   The migration guide highlights API changes in new versions.

Accord version 0.7.1 is available on Maven Central Repository. Scala versions 2.10.3+, 2.11.1+ and 2.12.0+ are supported. The next milestone is 0.8-SNAPSHOT and is available from the Sonatype snapshots repository.

SBT

Simply add the accord-core module to your build settings:

// Regular (JVM) Scala projects:
libraryDependencies += "com.wix" %% "accord-core" % "0.7.1"

// Scala.js projects:
libraryDependencies += "com.wix" %%% "accord-core" % "0.7.1"

// As a result of a Scala compiler bug in versions prior to 2.12.2, in some
// cases you may get "missing or invalid dependency detected while loading 
// class file" errors. Until a fix is released this can be worked around by
// adding the following your build script.
// (See issue #84 at https://github.com/wix/accord/issues/84)
libraryDependencies +=
  "org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided"

If you want to evaluate the upcoming snapshot release, add the Sonatype snapshot repository to your resolvers; typically this means adding the following to your build.sbt file:

resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"

// Regular (JVM) Scala projects:
libraryDependencies += "com.wix" %% "accord-core" % "0.8-SNAPSHOT"

// Scala.js projects:
libraryDependencies += "com.wix" %%% "accord-core" % "0.8-SNAPSHOT"

Maven

Accord is published to the Maven Central Repository, so you simply have to add the appropriate dependency to your POM:

<dependencies>
  <dependency>
    <groupId>com.wix</groupId>
    <artifactId>accord-core_${scala.tools.version}</artifactId>
    <version>0.7.1</version>
  </dependency>
  <!--
    As a result of a Scala compiler bug in versions prior to 2.12.1, in some
    cases you may get "missing or invalid dependency detected while loading 
    class file" errors. Until a fix is released this can be worked around by
    adding the following your build script.
    (See issue #84 at https://github.com/wix/accord/issues/84)
  -->
  <dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-compiler</artifactId>
    <version>${scala.version}</version>
  </dependency>
</dependencies>

If you want to evaluate the upcoming snapshot release, add the Sonatype snapshot repository and a dependency on Accord to your POM:

<repositories>
  <repository>
    <id>sonatype-snapshots</id>
    <name>Sonatype snapshot repository</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <releases><enabled>false</enabled></releases>
    <snapshots><enabled>true</enabled></snapshots>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>com.wix</groupId>
    <artifactId>accord-core_${scala.tools.version}</artifactId>
    <version>0.8-SNAPSHOT</version>
  </dependency>
</dependencies>