Provides object schema validation and normalization through the validateObject()
and normalizeObject()
functions.
This project is based on my previous OptionChecker
-project and is its direct successor.
npm install alcacode/object_validator
Download or clone the repository using git clone https://github.com/alcacode/object_validator.git
.
const schema = {
str: {
type: 'string',
// Reject values whose 'length' property is less than 1.
minLength: 1,
// Reject values whose 'length' property is greater than 10.
maxLength: 10,
// If the input was rejected, set the value to 'default'.
defaultValue: 'default'
},
num: {
type: 'number',
// Reject values smaller than 10.
min: 10,
// Reject values greater than 30.
max: 30,
// Reject NaN values.
notNaN: true,
// Function whose return value replace input of wrong type.
onWrongType: (v) => typeof v === 'string' ? +v : undefined
},
str2: {
macro: 'str'
}
}
// Just validate.
if (validateObject(schema, obj, options))
console.log("Object is valid!");
// Validate and return a normalized object.
const normalized = normalizeObject(schema, obj, options);
In the above example, normalized
is guaranteed to have str
property with a String
value of length between 1 and 10. If no valid str
option is provided, the value of str2
is used instead (provided that it is valid). If both str
and str2
are invalid or missing str
will recieve its default value 'default'
.
normalized
will have a num
property if a num
option with a non-NaN
Number
or String
coercable to a Number
value that is greater than or equal to 10
and less than or equal to 30
was provided.
- object_validator
- Installation
- Usage
- Table of Contents
- Option types
- The
Options
Object - The
ObjectSchema
ObjectObjectSchema.type
ObjectSchema.required
ObjectSchema.allowOverride
ObjectSchema.defaultValue
ObjectSchema.pattern
ObjectSchema.patternAction
ObjectSchema.passTest(value)
ObjectSchema.testFullValue
ObjectSchema.allowPartialPass
ObjectSchema.allowInherited
ObjectSchema.onWrongType(value)
ObjectSchema.onPass(value)
ObjectSchema.maxLength
ObjectSchema.minLength
ObjectSchema.instance
ObjectSchema.max
ObjectSchema.min
ObjectSchema.notFloat
ObjectSchema.notNaN
ObjectSchema.notInfinite
ObjectSchema.coerceType
ObjectSchema.compactArrayLike
ObjectSchema.mapTo
ObjectSchema.macro
ObjectSchema.extends
ObjectSchema.subRule
normalizeObject(schema[,obj][, options])
validateObject(schema[,obj][, options])
createNormalizer(schema[,options])
createValidator(schema[,options])
The following types can be used in ObjectSchema
. Type value is case-insensitive.
- object
- function
- number
- bigint
- string
- undefined
- boolean
- symbol
Macro types are types that expand to a built-in type with some specific configuration.
Macro for 'object' where instance
is Array
.
Macro for 'object' where instance
is Map
.
Macro for 'object' where instance
is Set
.
Macro for 'number' where isFloat
is false
.
Macro for 'object' where the only allowed value is null
.
Special types are types with specific behavior associated with them.
Allows any type to pass. Prevents onWrongType
from being called.
Any Array
, TypedArray
, or Object
with a Number
valued length
property and @@iterable
method returning well-formed iterables.
An iterable is considered well-formed when it has a value
property and a Boolean
valued done
property.
The options declaration object is used to declare the requirements of applicable to options and to tweak the behavior of validateObject()
.
- <
boolean
>
Overrides the default value of allowOverride
. Does not override individually set allowOverride
. Default: true
.
- <
boolean
>
If true
, a warning message will be emitted when reference errors or circular references are found. Default: true
.
- <
boolean
>
If true
, causes normalizeObject()
to return a null prototype object, otherwise its prototype will be Object
.
Default: true
.
- <
boolean
>
If true
, skips parsing schema with expandSchema()
. Used internally for createNormalizer
and createValidator
.
Default: false
.
- <
boolean
>
If true
, throw an exception if any rule contains circular references.
Default: false
.
{
rule_1: {
type: 'any',
extends: 'rule_2'
},
rule_2: {
extends: 'rule_1'
},
rule_3: {
macro: 'rule_1'
}
}
Resolving any of the above rules is impossible, because their reference chain contain themselves.
- <
boolean
>
If true
, throw a ReferenceError
if a rule contains references to non-existent rules.
Default: false
.
- <
boolean
>
If true
, throw an exception if any undeclared properties exist on the input object.
Default: false
.
- <
boolean
>
If true
, throw an exception if the input object contain any invalid values.
Default: false
.
Object specifying limits for individual options.
- <
string
>
Required. Case insensitive. One of 'object'
, 'function'
, 'number'
, 'bigint'
, 'string'
, 'undefined'
, 'boolean'
, 'symbol'
, 'array'
, 'null'
, or 'any'
.
Note: Although the option value is tested against the specified type, there are multiple ways of converting said value to an appropriate type. What it really means is that the resulting value of any conversion attempts must adhere to the specified type.
- <
boolean
>
If true
an exception will be thrown if the option is missing or its value is invalid.
- <
boolean
>
If true
, a mapped option may overwrite the option it is mapped to (the last valid value is used). If false
, a mapped option will only used when the option it is mapped to is either missing or invalid. Defaults to the value of the global allowOverride
.
- <
any
>
Value to use if option is missing or its value is invalid. If set, that option is guaranteed to exist in the parsed options object.
Note: If required
is true
this value is effectively ignored.
- <
RegExp
|string
>
Test input value against pattern. Action taken is controlled by patternAction
.
If pattern
is a string value, the following special tokens can be used (case sensitive):
*
Wildcard, matches anything.%d
Matches any number, including the fractional part. Only period/full stop decimal points are supported.%i
Matches any whole number.%s
Matches any non-whitespace character.%n
Matches newline.%w
Matches any whitespace character.%c
Matches any latin alphabet character (a-zA-Z).
Repeated tokens match exactly n times, where n is the number of repetitions.
For example %c%c%c
match exactly 3 latin alphabet characters and is equivalent to /^([a-zA-Z]{3})$/u
.
Note: Special token generation can be prevented by escaping the character.
Action performed on pattern
match. Default: 'pass'
.
Possible values:
'pass'
- Pass if pattern matches. (Default)'reject'
- Reject if pattern matches.'retain'
- Retain only matching characters.'discard'
- Discard matching characters.
Function used to test input value if value passed all other tests.
this
<undefined
>value
<any
> Value of the value currently being evaluated or its member items if an@@iterator
method is present.
- <
boolean
>
true
to validate value, false
to invalidate the value.
- <
boolean
>
Passes the entire option value to passTest()
even if an @@iterator
method is present. Does nothing if passTest()
is not present.
- <
boolean
>
If true
and passTest()
is present, instead of the entire value being discarded only the failing property will be discarded.
Note: This creates a new object of the same type as the option value is created by calling its constructor. Do not use this option if you do not know what that constructor does.
- <
boolean
>
If true
, extends property search to include the input object's prototype chain.
const schema = {
hasOwnProperty: {
type: 'function',
allowInherited: true
}
};
normalizeObject(schema, {}); // { hasOwnProperty: [Function: hasOwnProperty] }
Function called if the input value type does not match the type specified by the rule. Its return value is used to replace input value.
value
<any
> Value of the option currently being evaluated.
The function is called with this
set to null
.
Value replacing current input value.
Function called for each matched valid input value. Its return value is used as the final output value.
value
Input value currently being evaluated. Note that this value will not necessarily correspond to the actual raw input as it might have been transformed by other rules, such asonWrongType
.
The function is called with this
set to null
.
Final output value.
It is recommended that the return type be identical to that of the input value.
- <
number
>
Only applies where type
is 'string'
, 'object'
, 'function'
, or 'array'
. Discard the option if its length
property is greater than maxLength
, less than minLength
, or if no numeric length
property is present.
- <
object
> | <Function
>
Only applies where type
is 'object'
or 'function'
. Discard option if value is not an instance of instance
.
- <
number
>
Only applies where type
is 'number'
or 'bigint'
. Discard values greater than max
and/or less than min
.
- <
boolean
>
Only applies where type
is 'number'
. Discard non-integer values.
- <
boolean
>
Only applies where type
is 'number'
. Discard NaN
values.
- <
boolean
>
Only applies where type
is 'number'
. Discard non-finite values (Infinity
).
- <
boolean
>
Only applies where type
is 'bigint'
, 'boolean'
, 'number'
, or 'string'
. If true
, attempt to convert option value to the one specified in type
. Type coercion is performed before the final type check.
Values are convert to BigInt
by first converting the value to a Number
and then calling the BigInt()
function with that value as its argument. If conversion is not possible the value becomes null
.
Truthy values are converted to true
, the rest become false
.
Values of types other than BigInt
and Symbol
are converted to Number
s by using the unary + operator. BigInt
values are converted by calling the Number()
constructor with the value as its argument. Symbol
values are converted to NaN
.
Values are converted by performing string concatenation, with the exception of Symbol
values which are converted by calling the String()
constructor with the value as its argument.
Note: This occurs before onWrongType()
and transformFn()
are called.
- <
boolean
>
If true
, remove any gaps resulting from a partial pass. Instances of Array
and TypedArray
are considered array-like.
Note: Has no effect if allowPartialPass
is not true
.
- <
string
>
Map option to a different property key in the output object.
- <
string
>
Use the rules of another option and map output accordingly. All other options are discarded if set. If the referenced rule does not exist or forms a circular reference, a warning will be printed and the option will be discarded.
- <
string
>
Inherit rules from another rule. Settings defined on the extending rule take precedence over inherited rules. If the referenced rule does not exist or forms a circular reference, a warning will be printed and the option will be discarded.
{
options: {
firstOption: {
type: 'number',
min: 0,
max: 10,
defaultValue: 5,
coerceType: true
},
secondOption: {
type: 'number',
reference: 'firstOption',
max: 11
}
}
}
In the example above secondOption
, because it itself does not have them, will inherit min
, defaultValue
, and coerceType
from firstOption
. After references have been resolved, secondOption
is effectively equivallent to:
{
// ...
secondOption: {
type: 'number',
min: 0,
max: 11,
defaultValue: 5,
coerceType: true
}
}
- <
string
>
Only applies where type
is 'object'
. Schema describing nested object.
Note: If a sub-rule contains a required
rule its parent rules become implicitly required
, too. Setting required
to false
in the parent node causes any required
sub-rules to fail only if the parent node matched a value.
const schema1 = {
obj: {
type: 'object',
subRule: {
str: {
type: 'string',
required: true // Implicitly makes `obj` required.
}
}
}
};
const schema2 = {
obj2: {
type: 'object',
required: false,
subRule: {
str: {
type: 'string',
required: true // Only applies if `obj` matched a value.
}
}
}
};
validateObject(schema1, { obj: { str: "abc" } }); // true
validateObject(schema1, { obj: { str: 123 } }); // false
validateObject(schema2, { obj: { str: 123 } }); // false
validateObject(schema2, { }); // true
-
schema <
ObjectSchema
>
Object describing the structure of valid objects. -
obj <
object
>
Object to validate. -
options <
Options
>allowOverride
<boolean
> Default override behavior. Iftrue
macroed and mapped properties may replace existing values, iffalse
once a valid value has been assigned all other values mapped to that property key are discarded. Default:true
.throwOnCircularReference
<boolean
> Iftrue
, throw an exception if a circular reference is detected. Default:false
.throwOnReferenceError
<boolean
> Iftrue
, throw aReferenceError
if a rule references a non-existent rule. Default:false
.throwOnUnrecognized
<boolean
> Iftrue
, throw an exception if any undeclared properties exist onobj
. Default:false
.throwOnInvalid
<boolean
> Iftrue
, throw an exception ifobj
contain any invalid values. Default:false
.printWarnings
<boolean
> Iftrue
, a warning message will be emitted when reference errors or circular references are found. Default:true
.
- <
object
>
Normalized object. Contains options with valid values or its default value if one was defined in ObjectSchema.defaultValue
.
Note: By default, the returned Object
has null
as its prototype. See noReturnValuePrototype
for information on how to adjust this behavior.
- <
Error
> IfthrowOnCircularError
istrue
and a macro rule or rule reference forms a circular reference. - <
ReferenceError
> IfthrowOnReferenceError
istrue
and a rule references a non-existent rule. - <
Error
> IfthrowOnUnrecognized
istrue
and any undeclared properties exist on the input object. - <
Error
> IfthrowOnInvalid
istrue
and any value fails to validate. - If
ObjectSchema.required
is set totrue
on any rule and the input object does not contain a property mapping to that key or if all such values are invalid. The type of exception thrown is determined by the first failed criterion.
{
options: {
num: {
type: 'number',
min: 0,
notNaN: true,
defaultValue: 3
},
name: {
type: 'string',
minLength: 1,
required: true
}
}
}
In this example, the option num
must be a Number
greater than or equal to 0
and it must not be NaN
. If it fails any of those tests, or is missing, it will still appear in the parsed options object, but with its default value of 3
. The option name
must be present and it must be valid (String
whose length
is greater than or equal to 1
) or an exception will be raised due to required
being true
.
Returns true
if the provided object obj
conforms with schema
, false
otherwise.
Note: validateObject
uses normalizeObject
internally. It is therefore a mistake to first call validateObject
followed by normalizeObject
with the same arguments, instead just call normalizeObject
(in a try...catch
-statement if necessary).
-
schema <
ObjectSchema
>
Object describing the structure of valid objects. -
obj <
object
>
Object to validate. -
options <
Options
>allowOverride
<boolean
> Default override behavior. Iftrue
macroed and mapped properties may replace existing values, iffalse
once a valid value has been assigned all other values mapped to that property key are discarded. Default:true
.throwOnCircularReference
<boolean
> Iftrue
, throw an exception if a circular reference is detected. Default:false
.throwOnReferenceError
<boolean
> Iftrue
, throw aReferenceError
if a rule references a non-existent rule. Default:false
.throwOnUnrecognized
<boolean
> Iftrue
, throw an exception if any undeclared properties exist onobj
. Default:false
.throwOnInvalid
<boolean
> Iftrue
, throw an exception ifobj
contain any invalid values. Default:false
.printWarnings
<boolean
> Iftrue
, a warning message will be emitted when reference errors or circular references are found. Default:true
.
- <
boolean
>
Returns true
if obj
is valid, false
otherwise.
- <
Error
> IfthrowOnCircularError
istrue
and a macro rule or rule reference forms a circular reference. - <
ReferenceError
> IfthrowOnReferenceError
istrue
and a rule references a non-existent rule. - <
Error
> IfthrowOnUnrecognized
istrue
and any undeclared properties exist on the input object. - <
Error
> IfthrowOnInvalid
istrue
and any value fails to validate.
Creates a new function that take an input object as its only argument. When called the input object is passed to normalizeObject
along with the options it was created with and schema in its expanded form.
-
schema <
ObjectSchema
>
Object describing the structure of valid objects. -
options <
Options
>
Note:skipSchemaExpansion
is ignored as it is required internally.
- <
Function
>
Creates a new function that take an input object as its only argument. When called the input object is passed to validateObject
along with the options it was created with and schema in its expanded form.
-
schema <
ObjectSchema
>
Object describing the structure of valid objects. -
options <
Options
>
Note:skipSchemaExpansion
is ignored as it is required internally.
- <
Function
>