http://qs321.pair.com?node_id=1126803

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

I have a Perl hash that I need to write to JSON and to CSV formats.

A print Dumper( \%formdata ) of my hash looks like this.

$VAR1 = { 'SPRequest' => { 'xrelease' => '13038', 'macaddr' => '47:00:11:22:00:30', 'name' => 'localhost', 'description' => 'demo' }, '.submit' => bless( do{\(my $o = 1)}, 'JSON::PP::Boolean +' ), 'class' => 'SPRequest', '22406' => { 'win.profile' => 'production', 'win.os_version' => 'standard', 'win.os_part_size' => '1' } };

Here is the snipplet of code I use to produce my json file.

my $form_data_file = "/tmp/${hostname}_${macaddr}.json"; open FH, ">$form_data_file" or die "Could not open $form_data_file. :$ +!\n"; print FH to_json( \%formdata, {pretty=>1} ); close FH;

I am able to output my JSON to a file which looks like this:

[red@tools-dev1 psong]$ cat /tmp/localhost_47-00-11-22-00-30.json { "SPRequest" : { "xrelease" : "13038", "macaddr" : "47:00:11:22:00:30", "name" : "localhost", "description" : "demo" }, ".submit" : true, "class" : "SPRequest", "22406" : { "win.profile" : "production", "win.os_version" : "standard", "win.os_part_size" : "1" } }

Here is the code I am using to create my CSV file:

my $form_data_file_csv = "/tmp/${hostname}_${macaddr}.csv"; # Text::CSV::Slurp wants arrayref of hashref my $ARoHR = [ \%formdata ]; my $csv = Text::CSV::Slurp->create( input => $ARoHR); open FH, ">$form_data_file_csv" or die "Could not open $form_data_file +_csv. :$!\n"; print FH $csv; close FH;

But the problem is my CSV file which ends up looking like this:

[red@tools-dev1 psong]$ cat /tmp/localhost_47-00-11-22-00-30.csv ; ech +o .submit,22406,SPRequest,class true,HASH(0x8d81918),HASH(0x8d67980),SPRequest

What am I doing wrong here?

Replies are listed 'Best First'.
Re: Convert hash to CSV using Text::CSV::Slurp
by toolic (Bishop) on May 15, 2015 at 18:30 UTC
Re: Convert hash to CSV using Text::CSV::Slurp
by Plankton (Vicar) on May 15, 2015 at 20:27 UTC
    This seems to work for this particular instance of my problem:
    my @cols; my @row; sub hash2csv { my $h = shift; my $p = shift || 'top'; foreach my $k ( keys %{$h} ) { if (ref $h->{$k} eq ref {}) { hash2csv( $h->{$k}, $k ); } else { if ( $p eq 'top' ) { push @cols, $k; } else { push @cols, "$p.$k"; } push @row, $h->{$k}; } } }
    I wonder why I need Text::CSV::Slurp? Am I missing something? Will the above code break when passed other sorts of data?
      I wonder why I need Text::CSV::Slurp?
      According to its documentation, the create method of the Text::CSV::Slurp module can generate a CSV from an array of hashes. Here you have a hash of hashes, which is probably why you obtained scrambled output.

      Je suis Charlie.
      Hmm, I am not sure of what you do then with your @row and @cols arrays to populate your CSV.

      And what do you think will happen if you have other types of references (array refs, scalar refs, code refs, etc.) in your data structure? The program might probably not choke, but you'll see references (something like ARRAY(0x60005f6e0) in your output, instead of the actual data. Probably not what you want (although I am not entirely sure of what you want to obtain exactly).

      Je suis Charlie.
        print FH join( ',', @cols); print FH "\n"; print FH join( ',', @row); print FH "\n";
        And the developer of the API says I should always a expect HoH.