henzen has asked for the wisdom of the Perl Monks concerning the following question:
Greetings all,
Hopefully someone has used the Brannigan module before.
Validating whether a hash key is present works fine. However, I need to check whether unknown/junk keys are being submitted.
For example:
use strict;
use warnings;
use Brannigan;
use JSON;
use Data::Dumper;
my $json = q|
{
"method": "xxx",
"backend": {
"client": "mytest009",
"pw": "sdkjfhsfjhKJH87"
},
"blah": "123" # Junk
}|;
my $data = decode_json($json);
my $b = Brannigan->new({
name => 'jsonPost',
params => {
method => { required => 1, one_of => ['xxx', ], },
backend => {
hash => 1,
keys => {
client => { required => 1 },
pw => { required => 1 },
}
},
}
});
my $result = $b->process('jsonPost', $data);
if ($result->{_rejects}) {
print "ERROR\n";
print Dumper $result->{_rejects}, "\n";
}
else {
print "OK\n";
}
This code validates fine, but I need "blah" or any other unknown key to fail the validation.
Any ideas?
Thanks
Re: Brannigan: hash validation
by AnomalousMonk (Archbishop) on Feb 14, 2018 at 12:51 UTC
|
c:\@Work\Perl\monks\henzen>perl -wMstrict -MData::Dump -le
"use JSON;
;;
my $json = q{
{
\"method\": \"xxx\",
\"backend\": {
\"client\": \"mytest009\",
\"pw\": \"sdkjfhsfjhKJH87\"
},
\"blah\": \"123\"
}};
my $data = decode_json($json);
dd $data;
;;
my %valid = map { $_ => 1 } qw(method backend);
my @invalid = grep { ! exists $valid{$_} } keys %$data;
die qq{invalid keys(s) present: @invalid} if @invalid;
"
{
backend => { client => "mytest009", pw => "sdkjfhsfjhKJH87" },
blah => 123,
method => "xxx",
}
invalid keys(s) present: blah at -e line 1.
Of course, you have to know all the valid keys in advance, and it's only a top-level check, but maybe a starting point.
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |
Re: Brannigan: hash validation
by 1nickt (Canon) on Feb 14, 2018 at 13:28 UTC
|
Hi, I have never heard of that module (<RANT>And I think modules should have sensible, descriptive names!</RANT>).
I tried using JSON::Validator but it doesn't seem to support "additionalProperties": "false" even with its latest version (also it requires installing the entire Mojolicious application, which I think is silly).
JSON::Schema is even less up to date with newer JSON Schema versions, unfortunately, so I didn't try with that.
However, you can easily create a Type that will do what you want, using another of tobyink's creations, Type::Tiny:
use strict; use warnings;
package MyTypes {
use parent 'Type::Library';
use Type::Utils;
use Types::Standard qw/ Dict Enum Str /;
declare MyType => as Dict[
method => Enum['xxx'],
backend => Dict[
client => Str,
pw => Str,
],
];
};
package main {
use JSON;
MyTypes->import(qw/ +MyType /);
my $data = from_json q|{
"method": "xxx",
"backend": {
"client": "mytest009",
"pw": "sdkjfhsfjhKJH87"
},
"blah": "123"
}|;
assert_MyType( $data );
};
__END__
Output:
Reference {"backend" => {"client" => "mytest009","pw" => "sdkjfhsfjhKJ
+...} did not pass type constraint "MyType" at 1209129-2.pl line 31
"MyType" is a subtype of "Dict[backend=>Dict[client=>Str,pw=>Str],
+method=>Enum["xxx"]]"
Reference {"backend" => {"client" => "mytest009","pw" => "sdkjfhsf
+jhKJ...} did not pass type constraint "Dict[backend=>Dict[client=>Str
+,pw=>Str],method=>Enum["xxx"]]"
"Dict[backend=>Dict[client=>Str,pw=>Str],method=>Enum["xxx"]]" doe
+s not allow key "blah" to appear in hash
Hope this helps!
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
hmm thanks, lemme have a gander at this goodie...
| [reply] |
|
Thanks 1nickt,
This looks like it will work - I've been able to figure out most from the docs (I really wish module creators would have real-life examples, but anyway).
Is there a way to do an array count validation?:
use strict; use warnings;
package JSONTypes {
use parent 'Type::Library';
use Type::Utils;
use Types::Standard qw/ Dict Enum Str Tuple ArrayRef Optional Rege
+xpRef Int /;
declare JSONType => as Dict[
method => Enum[qw(xxx yyy)],
backend => Dict[
num => Int,
other => Optional[Str],
StrMatch[qr/^[a-z0-9]+$/]
],
# following works, but how to check that the array has at least
+ (say) 2 elements - {2,}
clientArr => ArrayRef[
Dict[ num => Int, ],
]
];
};
package main {
use JSON;
JSONTypes->import(qw/ +JSONType /);
my $data = from_json q|{
"method": "xxx",
"backend": {
"num": 1,
"client": "mytest009b"
},
"clientArr": [{ "num": "1" }, { "num": "2" }]
}|;
my $ret = eval { assert_JSONType( $data ); };
if ($@) {
print "ERROR\n$@\n";
}
else {
print "OK\n";
}
};
I'd appreciate any pointers.
Thanks
Edit: Figured out regex - use StrMatch[]
Edit 2: Validating array count can be done with an anon sub, but it then kills the other check:
clientArr => ArrayRef[
Dict[ num => Int, ],
],
clientArr => sub {
if (scalar @$_ < 2) {
print "ERROR: clientArr too small\n";
exit 1;
}
else {
}
return 1;
}
So I guess the question is how to combine those two checks (without having to hand code the num=>Int checks in pure Perl of course). | [reply] [d/l] [select] |
|
Re: Brannigan: hash validation
by Anonymous Monk on Feb 14, 2018 at 14:23 UTC
|
I tried and finally gave up on Brannigan. Wonderful idea, sort of like what happens when YACC meets XSLT. But it is so generalized that I could never get it to a point where I was confident that it was doing what I wanted. It seems better suited for checking what data is, but not so much for detecting when extraneous data exists (which seems to be your use-case). I cut my losses and did it the hard way. | [reply] |
|
| [reply] |
|
| [reply] |
|
| [reply] |
|
|
|
| [reply] |
|
|