http://www.perlmonks.org?node_id=1075635

Hello dear monks!

I regularly met the problem of arbitrary data structures validation, which comes in form either hierarchical config or JSON data. The substantial idea, I got from one of Perl books (I think, this is Hight Order Perl) is the following: the programming languages have tendency to be declarative (i.e. declaring/describing the result, but not the way, how to archive it) but they'll never completely be so, because it seems to be possible only in some local areas.

When such a local area is been invented, then an extremely useful micro-language will appear. For example, well known regular expressions for the area of arbitrary text data matching/extraction. Another successful example I know is the XPath (or XPointer?) technology for nodes matching in XML documents.

The last one seems to be very successful in addressing data nodes, that a lot modules appeared, that try to mimic XPath behaviour: Data::DPath, Data::SPath, Data::PathSimple, Class::XPath.

Well, XML seems to be not too modern, too heavyweight, too enterprisish. So, the minor brother, not overcumbered with namespaces and processing instructions, appeared. It is JSON. The related data extractions/matching technology appeared a bit later; this is JSON pointer: JSON::Pointer, Mojo::JSON::Pointer.

So, my intention was to develop module, which takes the best from the two worlds: declarative data path selection (a-la JSON Pointer and XPath, but not as simple as the first, and (yet) not as complex and feature-rich as the second), and from the perl (closures, flexibility, application agnosticism, DWIM and DRY principles).

Here come a few snipplets, from which you can judge about the module

use Data::DynamicValidator qw/validator/; my $data = { ports => [2222] }; my $errors = validator($data)->( on => '/ports/*', should => sub { @_ > 0 }, because => 'At least one port should be defined at "ports" section', )->errors; if(!@$errors){ say "all ok"; } else { say $_->reason for(@$errors); }

So, it generally, it uses triplets: on (specifies data path), should (specifies testing perl closure for the results of data path selection), and because (defines human-readable string for administrator to say/describe him the errors in a config, or for HTTP client developer, that something is missing in JSON input data).

A bit more complex example. Say, you want to check that all declared ports should be available for the application at startup. So, you should do the following:

use Net::EmptyPort qw(check_port); my $errors = validator($data)->( on => '/ports/*', should => sub { @_ > 0 }, because => 'At least one port should be defined at "ports" section', each => sub { my $port = $_->value; shift->report_error("The port $port is not available for usage") if(!check_port($port)); } )->errors;

The more complex examples are available in metacpan.

Constructive critique and suggestions are more then welcome!

Replies are listed 'Best First'.
Re: Announcing Data::DynamicValidator
by Anonymous Monk on Feb 21, 2014 at 01:28 UTC
    Get rid of Dynamic from the name :) I can tell it doesn't belong just by the virtue of the fact its there :) in perl most everything is dynamic

    once you have got rid of that you're left with Data::Validator which already exists :) you've entered the crowded field of validators, the best way to distinguish yourself is to compare/constrast/survey the competition