zigorou / perl-JSV

JSON Schema implementation for Perl
Other
25 stars 17 forks source link

Filling default value option #12

Open zigorou opened 11 years ago

natlibfi-arlehiko commented 8 years ago

This would be a real nice addition.

maksym3d commented 7 years ago

This is a code I'm using to put defaults on the schema based on a provide instance of this schema:

sub walkSchemaAndInstance {
    my ($schema, $schemaPart, $instancePart) = @_;
    if ( ref $instancePart eq 'HASH' ) {
        foreach my $key (keys %{$instancePart}) {
            if (not exists $schemaPart->{$key}) {
                die "Instance does not mathch schema at key [$key] while trying to assign defaults"
            } else {
                if (exists $schemaPart->{$key}{'$'.'ref'}) {
                    my $ref = $schemaPart->{$key}{'$'.'ref'};
                    $ref =~ s/^#\///;
                    my $definition = $schema;
                    foreach my $refKey (split('/', $ref)) {
                       $definition = $definition->{$refKey};
                    }
                    $schemaPart->{$key} = dclone $definition;
                }
                if ($schemaPart->{$key}{type} eq 'object' and exists $schemaPart->{$key}{enum}) {
                    $schemaPart->{$key}{default} = $instancePart->{$key};
                } elsif ($schemaPart->{$key}{type} eq 'object' and exists $schemaPart->{$key}{properties}) {
                    walkSchemaAndInstance($schemaPart->{$key}{properties}, $instancePart->{$key});
                } else {
                    walkSchemaAndInstance($schemaPart->{$key}, $instancePart->{$key});
                }
            };
        }
    } elsif ( ref $instancePart eq 'ARRAY' ) {
        die "Deafault values on complex array types are not supported yet" unless ($schemaPart->{items}{type} ne 'object' || exists $schemaPart->{items}{enum});
        $schemaPart->{default} = $instancePart;
    } else {
        die unless (ref $schemaPart eq 'HASH' and $schemaPart->{type} ne 'object');
        $schemaPart->{default} = $instancePart;
    }
}

sub getSchemaWithDefaults {
    my ($validator, $schema, $instance) = @_;
    die "Supplied default values do not comply with specified schema" unless ( $validator->validate(dclone $schema, dclone $instance) );
    my $schemaFused =  dclone $schema;
    walkSchemaAndInstance($schema, $schemaFused->{properties}, $instance);
    return $schemaFused;
}