I think the popularity of JSON (and CSS/XPath selectors) has recently caused a bunch of people to think along these lines (i.e, a syntax for paths to query deeply nested data structures).
I'm much slower at writing code than Sawyer; however I bet I can find 3 more complete implementations of whatever I wanted to write on CPAN in less time than it would take me to pick a package name ;)
https://metacpan.org/module/JSON::Path
https://metacpan.org/module/Hash::Path
https://metacpan.org/module/Data::Path

On 09/11/2011 04:20 PM, sawyer x wrote:
On Sun, Sep 11, 2011 at 4:00 PM, Chanan Berler <[email protected]> wrote:
is this better ?

No. Eval is bad! :)

Imagine you send improper text that could be interpreted as actual code. Imagine someone else being able to send stuff to that service and sends something malicious. Imagine someone not knowing what they're suppose to send, and they just send commands.

Instead, I suggest one of two options:
1. Using some form of syntax to say "please look into this key, and then that key, and then this index number for the value" and then using some parser (or writing your own) that is able to understand it. This is what's done in XPath, CSS selector paths, etc.
2. sending the data itself instead of sending a reference to where the data may be. I suggest JSON,

I've gone ahead and written the 1st option, for fun:
#!/usr/bin/perl
use strict;
use warnings;

{
    package NewHash;
    use Tie::Hash;

    our @ISA = ('Tie::StdHash');

    sub FETCH {
        my ( $object, $path ) = @_;
        my @paths = split /\//, $path;
        return iterate( $object->{ shift @paths }, @paths );
    }

    sub iterate {
        my ( $object, @paths ) = @_;
        my $next = shift @paths if @paths;

        if ( ref $object eq 'HASH' ) {
            return defined $next ? iterate( $object->{$next}, @paths ) : $object;
        } elsif ( ref $object eq 'ARRAY' ) {
            return defined $next ? iterate( $object->[$next], @paths ) : $object;
        }

        if ( $next && ! ref $object ) {
            die 'Unsupported reference type: ' . ref $object;
        }

        return $object;
    }

}


my %hash;
tie %hash, 'NewHash';

%hash = (
    key1 => {
        key2 => [ 'val' ],
    },
);

my $location = 'key1/key2/0';
print $hash{$location}; # prints 'val'

print $hash{'key1'}; # prints { key2 => ['val'] }
print $hash{'key1/key2'}; # prints ['val']

-----

This recurses over the path, and goes deeper for every result until it either finds the exact location or reaches a scalar, which should be the last location. It doesn't support SCALAR refs or CODE refs or Regexp refs, but it can be adapted to support them.

The problem here is what if the key name contains a forward slash? Ah, the fallacy of simple parsing. :)

Good luck.
S.


_______________________________________________
Perl mailing list
[email protected]
http://mail.perl.org.il/mailman/listinfo/perl



--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.


_______________________________________________
Perl mailing list
[email protected]
http://mail.perl.org.il/mailman/listinfo/perl

Reply via email to