nmerriweather has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to figure out a way to use map to export a perl data structure to a JSON structure

my perl structure is an array of arrays such (its a list of image srcs + attributes (in this example, a js function)):
@{$_[0]->{'images'}{'section_a'}} = ( [ "image1.gif" , "mark('a',1)" ], [ "image2.gif" , "mark('a',2)" ], );
i need to conert it to this:
[ ["image1.gif","mark('a',1)"],["image2.gif","mark('a',2)"] ] ]
as you can see, its pretty simple

i'm currently doing this output with a forloop -- but i'd rather do it in a clean lookin map{} -- i just have no idea how

can anyone suggest an approach?

Replies are listed 'Best First'.
Re: help needed with map
by mrkoffee (Scribe) on Sep 29, 2005 at 22:54 UTC

    I managed to convert the section in your example into a string in JSON notation using the following:

    my $section = [ [ "image1.gif" , "mark('a' ,1)" ], [ "image2.gif" , "mark('a' ,2)" ], ]; my $parsed = '[ ' . join( ' , ', map { '[ "' . join('" , "', @$_) . '" ]' } @ +$section ) . ' ]';

    $parsed will contain the following string:

    [ [ "image1.gif" , "mark('a' ,1)" ] , [ "image2.gif" , "mark('a' ,2)" +] ]

    which is (I think) what you want. (There's an extra square bracket in your example, which I omitted.)

    It does use map, among other things, though I'm not sure it qualifies for "clean-lookin". I found a CPAN module called JSON which produced the same result more cleanly, and would probably be easier to maintain:

    use JSON; my $json = JSON->new; my $section = [ [ "image1.gif" , "mark('a' ,1)" ], [ "image2.gif" , "mark('a' ,2)" ], ]; my $parsed = $json->objToJson( $section );
Re: help needed with map
by ikegami (Patriarch) on Sep 29, 2005 at 22:23 UTC

    I'm not sure I understand correct since the two snippets are equivalent. I'm assuming you're looking for help converting the memory structure in the first snippet into the string shown in the second snippet. This works:

    sub bracket { local $_ = @_ ? $_[0] : $_; return "[ $_ ]"; } sub quote { local $_ = @_ ? $_[0] : $_; s/(["\\])/\\$1/g; return qq{"$_"}; } @{$_[0]->{'images'}{'section_a'}} = ( [ "image1.gif" , "mark('a',1)" ], [ "image2.gif" , "mark('a',2)" ], ); print( bracket # Put brackets around the row. join ',', # Join the records. map { # For each record, bracket # Put brackets around each record. join ',', # Join the fields. map quote, @$_ # Quote and escape the fields. } @{$_[0]->{'images'}{'section_a'}} ); __END__ output ====== [ [ "image1.gif","mark('a',1)" ],[ "image2.gif","mark('a',2)" ] ]

    You may want to use Data::Dumper instead.

Re: help needed with map
by Skeeve (Parson) on Sep 29, 2005 at 22:50 UTC
    I also don't understand what you really want to achieve. If you got a for-loop, why not show it. I think that'll be more easy to understand.

    $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
Re: help needed with map
by Roy Johnson (Monsignor) on Sep 29, 2005 at 23:15 UTC
    Take a look at reduce from List::Util. I think you want something like the third line of this litttle program:
    my @foo = ([qw(one two)], [qw(three four)], [qw(five six)]); # use List::Util 'reduce'; # oops: my $str = reduce {"[$a,$b]"} map { reduce {"[$a,$b]"} @$_ } @f +oo; my $str = sprintf "[%s]", join ',', map { sprintf '["%s"]', join '","' +, @$_} @foo; print "--- $str ---\n";
    Thanks to Anonymonk for pointing out that I had tested insufficiently. And now I've got the quoting. But I'm not using reduce anymore.

    Caution: Contents may have been coded under pressure.
      #!/usr/bin/perl -w use strict; my @foo = ([qw(one two)], [qw(three four)], [qw(five six)]); use List::Util 'reduce'; my $str = reduce {"[$a,$b]"} map { reduce {"[$a,$b]"} @$_ } @foo; print "--- $str ---\n"; my $seen = 0; $str = reduce { $seen++ ? $a.",[$$b[0],$$b[1]]" : "[$$a[0],$$a[1]],[$$b[0],$$b[1]]" } @foo; print "--- [$str] ---\n";
Re: help needed with map
by Roy Johnson (Monsignor) on Sep 30, 2005 at 01:24 UTC
    You can use Data::Dumper:
    use Data::Dumper; ($str) = Dumper(\@foo) =~ /=(.*);$/s; $str =~ tr/' \n/"/d;
    :-)

    Caution: Contents may have been coded under pressure.
Re: help needed with map
by Corion (Patriarch) on Sep 30, 2005 at 06:48 UTC

    What's wrong with using JSON to convert data from and to JSON notation?