Data Validation
Key takeaways
Schema | Defines validation schemas. |
NotRule | Negates a rule. |
AndRule | Validates combinations of rules created with AND logical operations. |
OrRule | Validates combinations of rules created with OR logical operations. |
IncludedRule | Checks that a list contains only specified values. |
ExcludedRule | Verifies that none of the values specified in the rule is present in a list of constants. |
AtLeastOneExistsRule | Checks that given a set of properties, at least one of them exists. |
ValueComparisonRule | Compares a value to a constant. |
Introduction
In this tutorial, we will learn how to use a set of validation rules available in the Pip.Services toolkit. First, we will see the necessary pre-requisites. Then, we will see the Schema class, which provides a way to create validation schemas. Lastly, we will see the different validation rules through the use of examples.
Data validation
Pre-requisites
In order to perform validations, we need to import the Schema class and the different validation rules that we want to use. The following example shows how to import the Schema class and two validation rules named ValueComparisonRule and AndRule.
import { AndRule, Schema, ValueComparisonRule } from "pip-services4-data-node"
import (
validate "github.com/pip-services4/pip-services4-go/pip-services4-data-go/validate"
)
from pip_services4_data.validate import Schema, ValueComparisonRule, AndRule
The schema component
The Schema class provides a mechanism to create validation schemas, which can later be used to validate objects, project properties, arrays and maps.
There are two ways to create a validation schema. The first is to create an instance of the Schema class and use a list with our validation rules as an input parameter. An example of this is:
// Comparing 1 < x < 10 by using a list of rules
let myRules = [new ValueComparisonRule("LTE", 10), new ValueComparisonRule("GTE", 1)];
let mySchema1 = new Schema(false, myRules);
// Comparing 1 < x < 10 by using a list of rules
myRules := []validate.IValidationRule{validate.NewValueComparisonRule("LTE", 10), validate.NewValueComparisonRule("GTE", 1)}
mySchema := validate.NewSchemaWithRules(false, myRules)
# Comparing 1 < x < 10 by using a list of rules
my_rules = [ValueComparisonRule("LTE", 10), ValueComparisonRule("GTE", 1)]
my_schema1 = Schema(rules=my_rules)
Alternatively, we can first create an instance and define our rule using the with_rule() method. An example of this approach is:
// Comparing 1 < x < 10 by using the AND rule
let mySchema2 = new Schema().withRule(new AndRule(new ValueComparisonRule("GTE", 1), new ValueComparisonRule("LTE", 10)));
// Comparing 1 < x < 10 by using the AND rule
mySchema2 := validate.NewSchema().WithRule(
validate.NewAndRule(
validate.NewValueComparisonRule("GTE", 1),
validate.NewValueComparisonRule("LTE", 10),
))
# Comparing 1 < x < 10 by using the AND rule
my_schema2 = Schema().with_rule(AndRule(ValueComparisonRule("GTE", 1), ValueComparisonRule("LTE", 10)))
Validation mechanism
To perform a validation based on a specified schema, we need to use the validate() method available from the Schema() class.
This method returns an empty list if the validation was successful, and a list with result information if it wasn’t. As a result, we need to differentiate between both cases, and for the unsuccessful option, we need to invoke the method get_message() and/or get_code() to obtain the reason for failure and/or the result code.
In the example below, we examine two cases based on the rule that the value must be between one and ten. In the first case, we evaluate the value 0, which results in a BAD_VALUE code and the message “must GTE 1 but found 0”. In the second case, we evaluate 5, which results in an empty list and the message “Value within range”.
// Comparing 1 <= x <= 10 by using a list of rules
let myRules = [new ValueComparisonRule("LTE", 10), new ValueComparisonRule("GTE", 1) ];
let schema = new Schema(false, myRules);
// Case 1: bad value
let validation = schema.validate(0);
if (validation.length > 0) {
// Case: bad value
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
} else {
// Case: good value
console.log("Value within range");
}
// Case 2: good value
validation = schema.validate(5);
if (validation.length > 0) {
// Case: bad value
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
else {
// Case: good value
console.log("Value within range");
}
// Comparing 1 <= x <= 10 by using a list of rules
myRules := []validate.IValidationRule{
validate.NewValueComparisonRule("LTE", 10),
validate.NewValueComparisonRule("GTE", 1),
}
mySchema := validate.NewSchemaWithRules(false, myRules)
// Case 1: bad value
validation := mySchema.Validate(0)
if len(validation) > 0 {
// Case: bad value
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
} else {
// Case: good value
fmt.Println("Value within range")
}
// Case 2: good value
validation = mySchema.Validate(5)
if len(validation) > 0 {
// Case: bad value
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
} else {
// Case: good value
fmt.Println("Value within range")
}
# Comparing 1 <= x <= 10 by using a list of rules
my_rules = [ValueComparisonRule("LTE", 10), ValueComparisonRule("GTE", 1)]
schema = Schema(rules=my_rules)
validation = schema.validate(0)
# Case 1: bad value
if len(validation) > 0:
# Case: bad value
print(validation[0].get_message())
print(validation[0].get_code())
else:
# Case: good value
print("Value within range")
# Case 2: good value
validate_schema1_2 = schema.validate(5)
if len(validate_schema1_2) > 0:
# Case: bad value
print(validate_schema1_2[0].get_message())
print(validate_schema1_2[0].get_code())
else:
# Case: good value
print("Value within range")
After running the above code, we get the following results:
Validation rules
Pip.Services provides a comprehensive set of validation rules. In this section, we will see an explanation and examples of each of them.
NotRule
The NotRule class allows us to negate a given rule. The examples below show how to use it.
// NotRule - Case: value different from 1
let schema = new Schema().withRule(new NotRule(new ValueComparisonRule("EQ", 1)));
// Case 1: good value
let validation = schema.validate(2);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(1);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// NotRule - Case: value different from 1
schema := validate.NewSchema().WithRule(validate.NewNotRule(validate.NewValueComparisonRule("EQ", 1)))
// Case 1: good value
validation := schema.Validate(2)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(1)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# NotRule - Case: value different from 1
from pip_services4_data.validate import Schema,NotRule
schema = Schema().with_rule(NotRule(ValueComparisonRule("EQ", 1)))
# Case 1: good value
validation = schema.validate(2)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(1)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
AndRule
The AndRule class allows us to validate combinations of rules created with AND logical operations. The examples below show how to use it.
// AndRule - Case: 1<= x <= 10
let schema = new Schema().withRule(new AndRule(new ValueComparisonRule("GTE", 1), new ValueComparisonRule("LTE", 10)));
// Case 1: good value
let validation = schema.validate(1);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(12);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// AndRule - Case: 1<= x <= 10
schema := validate.NewSchema().WithRule(validate.NewAndRule(
validate.NewValueComparisonRule("GTE", 1),
validate.NewValueComparisonRule("LTE", 10),
))
// Case 1: good value
validation := schema.Validate(1)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(12)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# AndRule - Case: 1<= x <= 10
from pip_services4_data.validate import Schema,AndRule
schema = Schema().with_rule(AndRule(ValueComparisonRule("GTE", 1), ValueComparisonRule("LTE", 10)))
# Case 1: good value
validation = schema.validate(1)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(12)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
OrRule
The OrRule class allows us to validate combinations of rules created with OR logical operations. The examples below show how to use it.
// Or rule - Case x < 1 OR x > 10
let schema = new Schema().withRule(new OrRule(new ValueComparisonRule("LT", 1), new ValueComparisonRule("GT", 10)));
// Case 1: good value
let validation = schema.validate(0);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(5);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Or rule - Case x < 1 OR x > 10
schema := validate.NewSchema().WithRule(validate.NewOrRule(
validate.NewValueComparisonRule("LT", 1),
validate.NewValueComparisonRule("GT", 10),
))
// Case 1: good value
validation := schema.Validate(0)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(5)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# Or rule - Case x < 1 OR x > 10
from pip_services4_data.validate import Schema,OrRule
schema = Schema().with_rule(OrRule(ValueComparisonRule("LT", 1), ValueComparisonRule("GT", 10)))
# Case 1: good value
validation = schema.validate(0)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(5)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
IncludedRule
The IncludedRule class allows us to check that a value is included in a given set of constants. The examples below show how to use it.
// Included rule - Case: include 1, 2, 3
let schema = new Schema().withRule(new IncludedRule(1, 2, 3));
// Case 1: good value
let validation = schema.validate(2);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(10);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Included rule - Case: include 1, 2, 3
schema := validate.NewSchema().WithRule(validate.NewIncludedRule(1, 2, 3))
// Case 1: good value
validation := schema.Validate(2)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(10)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# Included rule - Case: include 1, 2, 3
from pip_services4_data.validate import Schema,IncludedRule
schema = Schema().with_rule(IncludedRule(1, 2, 3))
# Case 1: good value
validation = schema.validate(2)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(10)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
ExcludedRule
The ExcludedRule allows us to verify that a value is not included in a given set of constants. The examples below show how to use it.
// Excluded rule - Case: excluded values are 1, 2 3
let schema = new Schema().withRule(new ExcludedRule(1, 2, 3));
// Case 1: good value
let validation = schema.validate(10);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(2);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Excluded rule - Case: excluded values are 1, 2 3
schema := validate.NewSchema().WithRule(validate.NewExcludedRule(1, 2, 3))
// Case 1: good value
validation := schema.Validate(10)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(2)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# Excluded rule - Case: excluded values are 1, 2 3
from pip_services4_data.validate import Schema,ExcludedRule
#
schema = Schema().with_rule(ExcludedRule(1, 2, 3))
# Case 1: good value
validation = schema.validate(10)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(2)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
AtLeastOneExistsRule
The AtLeastOneExistsRule class allows us to check that given a set of properties, at least one of them exists. The examples below show how to use it.
// Rule At least one exists - Case: field1, field2
let schema = new Schema().withRule(new AtLeastOneExistsRule("field1", "field2"));
// Case 1: good value
let validation = schema.validate({ "field1": 1 , "field2": "A" });
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(2);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Rule At least one exists - Case: field1, field2
schema := validate.NewSchema().WithRule(validate.NewAtLeastOneExistsRule("field1", "field2"))
// Case 1: good value
validation := schema.Validate(map[string]interface{}{"field1": 1, "field2": "A"})
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(map[string]interface{}{})
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
# Rule At least one exists - Case: field1, field2
from pip_services4_data.validate import Schema,AtLeastOneExistsRule
schema = Schema().with_rule(AtLeastOneExistsRule("field1", "field2"))
# Case 1: good value
validation = schema.validate({ 'field1': 1, 'field2': "A" })
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate({ })
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
ValueComparisonRule
The ValueComparisonRule class allows us to create a validation rule that compares a value to a constant. The following examples show how to use it.
var schema = new Schema().withRule(new ValueComparisonRule("LT", 1));
// Case 1: good value
var validation = schema.validate(0);
if (validation.length == 0) {
console.log("No errors");
} else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
// Case 2: bad value
validation = schema.validate(5);
if (validation.length == 0) {
console.log("No errors");
}
else {
console.log(validation[0].getMessage());
console.log(validation[0].getCode());
}
schema := validate.NewSchema().WithRule(validate.NewValueComparisonRule("LT", 1))
// Case 1: good value
validation := schema.Validate(0)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
// Case 2: bad value
validation = schema.Validate(5)
if len(validation) == 0 {
fmt.Println("No errors")
} else {
fmt.Println(validation[0].Message())
fmt.Println(validation[0].Code())
}
from pip_services4_data.validate import Schema, ValueComparisonRule
# Case x < 1
schema = Schema().with_rule(ValueComparisonRule("LT", 1))
# Case 1: good value
validation = schema.validate(0)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
# Case 2: bad value
validation = schema.validate(5)
if len(validation) == 0:
print("No errors")
else:
print(validation[0].get_message())
print(validation[0].get_code())
After running the above code, we get the following output:
Wrapping up
In this tutorial, we have seen how to create different types of validation rules and apply them to different situations. These rules included NotRule, AndRule, OrRule, IncludedRule, ExcludedRule and AtLestOneExistsRule.
These rules are valuable in cases where we have to compile highly complex logical expressions, as they help to simplify our code, and thus, avoid unintentional errors.