-2

I have a Perl Data::Dumper file (data.txt) with two arrays that i need to convert into JSON.

Here's what looks like my data.txt:

$stats = {
  'oldtime' => '04',
  'parsedlines' => 8,
  'day_lines' => [
    undef,
    8
  ],
  'actions' => {
    'microbe' => 1
  },
  'lastnick' => 'Sky',
  'words' => {
    'Sky' => 1,
    'microbe' => 9
  },
  'times' => {
    '04' => 8
  },
  'totallines' => 8,
  'word_times' => {
    'microbe' => [
      9
    ],
    'Sky' => [
      1
    ]
  },
  'lastvisited' => {
    'microbe' => 1,
    'Parts:' => 1,
    'Sky' => 1
  },
  'line_times' => {
    'microbe' => [
      3
    ],
    'Sky' => [
      1
    ]
  },
  'lengths' => {
    'microbe' => 36,
    'Sky' => 11
  },
  'lastnormal' => '[04:35:01] <Sky> ;algkagkaga
',
  'day_times' => [
    undef,
    [
      8,
      0,
      0,
      0
    ]
  ],
  'days' => 1,
  'joins' => {
    'microbe' => 1,
    'Sky' => 1
  },
  'monocount' => 0,
  'lines' => {
    'Sky' => 1,
    'microbe' => 3
  }
};
$lines = {
  'actionlines' => {
    'microbe' => [
      '[04:33:53] * microbe is doing just a test
'
    ]
  },
  'sayings' => {
    'Sky' => [
      ';algkagkaga'
    ],
    'microbe' => [
      'Hello'
    ]
  }
};

So as you can see, there is 2 arrays: $stats and $lines.
I want to convert them in JSON.
Someone on here (Borodin) came with a working solution, but it output only the second array ($lines). Here's his solution:

use strict;
use warnings qw/ all FATAL /;

use JSON;

print encode_json( do 'data.txt' or die $! ), "\n";  

But here's what it output:

{

    "actionlines":{
        "microbe":[
            "[04:33:53] * microbe is doing just a test\n"
        ]
    },
    "sayings":{
        "microbe":[
            "Hello"
        ],
        "Sky":[
            ";algkagkaga"
        ]
    }

}

So it output only $lines array... Any idea of what i can do to have it working ?

Math
  • 666
  • 8
  • 26
  • Your [original question](http://stackoverflow.com/questions/35690380/use-a-perls-datadumper-format-array-in-php) stated very clearly that your data file had only a single array – Borodin Feb 29 '16 at 07:31

2 Answers2

1

To access the hash references in your data file separately, you need to declare them using our before executing the do

Like this

use strict;
use warnings 'all';

use JSON;

our ( $stats, $lines );

do 'data.txt' or die $!;

print encode_json( $stats ), "\n";
print encode_json( $lines ), "\n";

output

{"day_times":[null,[8,0,0,0]],"actions":{"microbe":1},"lines":{"microbe":3,"Sky":1},"days":1,"lastnick":"Sky","oldtime":"04","words":{"Sky":1,"microbe":9},"lastnormal":"[04:35:01] <Sky> ;algkagkaga\n","times":{"04":8},"joins":{"Sky":1,"microbe":1},"totallines":8,"monocount":0,"lastvisited":{"Parts:":1,"microbe":1,"Sky":1},"word_times":{"microbe":[9],"Sky":[1]},"line_times":{"Sky":[1],"microbe":[3]},"parsedlines":8,"lengths":{"Sky":11,"microbe":36},"day_lines":[null,8]}
{"sayings":{"microbe":["Hello"],"Sky":[";algkagkaga"]},"actionlines":{"microbe":["[04:33:53] * microbe is doing just a test\n"]}}
Borodin
  • 126,100
  • 9
  • 70
  • 144
0

You don't have two arrays. You have two hashes.

Your code calls do and passes its return value as the only argument of encode_json(). From the perldoc:

If the file is successfully compiled, do returns the value of the last expression evaluated.

What that means is you're passing the value of the last expression in your data.txt file as the argument to encode_json(). That value is the hash that was assigned to $lines.

Possible solutions:

  1. Combine the two hashes into a single array of hashes when generating data.txt.

  2. Execute the data.txt file prior to the encode_json() call, ignoring its return value. Then, combine the two variables into an anonymous array by referencing them by package-qualified name. Because their declarations were not preceded by my, and they were declared inside the main package implicitly, the package will be main. Here's how it would look:


require('data.txt');
print encode_json([$main::stats,$main::lines]), "\n";
bgoldst
  • 34,190
  • 6
  • 38
  • 64