2

I am trying to read a perl associative array in my PHP script. For this firstly I am trying to convert perl hash to JSON using JSON module.

Below is the perl script I am using to convert associative array to JSON. The file toc.pl has the associative array "asc_array".

use JSON;
$j = new JSON;

require'toc.pl';

print encode_json \%asc_array; 

The asc_array looks like

%asc_array  = (
    "1"            => 'Introduction',
    "1.1"          => 'Scope',
    "1.2"          => 'Purpose',
    "2"            => 'Terminology',
    "2.1"          => 'Definitions',
    "2.2"          => 'Service Primitives',
    "2.3"          => 'Abbreviations',
    "2.4"          => 'Acronyms',
);

Here I am facing an issue and that is after converting it to JSON the order of associative array elements change.

So my question is How can I keep the order of elements even after converting it to JSON?

And, after converting it to JSON I am reading the JSON in PHP script.

Is there any better way to read perl associative array in PHP script?

user2109788
  • 1,266
  • 2
  • 12
  • 29
  • 1
    An associative array (hash) haven't any order. – Toto Sep 18 '14 at 11:05
  • 1
    Why do you want to have a specific order? – Toto Sep 18 '14 at 11:06
  • 1
    http://stackoverflow.com/a/4920304/223226 So you can't rely on hash keys order, nor on javascript object properties order. Use array instead. – mpapec Sep 18 '14 at 11:08
  • @M42 : I am storing table of contents with section number as keys and title as value. I used perl associative array for that. While looping over it in perl it was in order but, after converting to JSON the order changed. So what would you suggest to solve the above? – user2109788 Sep 18 '14 at 11:47
  • @user2109788: Could you show an extract of `%asc_array` and what order do you need. As @mpapec said above you may use an array instead. – Toto Sep 18 '14 at 11:49
  • @M42 : I have edited my question with an example of asc_array – user2109788 Sep 18 '14 at 11:56
  • 1
    What Perl resources are you reading where you are picking up the term "associative arrays"? Since Perl 5 was release twenty years ago, they have been called "hashes" in Perl. Whatever resources you are using seem to be horribly out of date. – Dave Cross Sep 18 '14 at 12:05
  • I have very less knowledge on perl. I just googled for it. And I was thinking that hash will not keep the order but associative arrays will do. Basically I was searching something similar to Python's Ordered Dict(https://docs.python.org/2/library/collections.html#collections.OrderedDict) in perl. – user2109788 Sep 18 '14 at 12:14
  • You have to sort the decoded JSON by key in the php script. – Toto Sep 18 '14 at 12:34
  • Like others have stated above I don't know why preserving the order is important and perl hashes are unordered structures. That being said I believe that Tie::Hash can be used to preserve the hash order. Disclaimer - it has been a while since I used the Tie modules. – Elsporko Sep 18 '14 at 12:41

2 Answers2

2

Use JSON->canonical to sort the keys

use JSON;

my %asc_array = (
    "1"   => 'Introduction',
    "1.1" => 'Scope',
    "1.2" => 'Purpose',
    "2"   => 'Terminology',
    "2.1" => 'Definitions',
    "2.2" => 'Service Primitives',
    "2.3" => 'Abbreviations',
    "2.4" => 'Acronyms',
);

print JSON->new->canonical(1)->encode( \%asc_array ), "\n";

Output:

{"1":"Introduction","1.1":"Scope","1.2":"Purpose","2":"Terminology","2.1":"Definitions","2.2":"Service Primitives","2.3":"Abbreviations","2.4":"Acronyms"}
Miller
  • 34,962
  • 4
  • 39
  • 60
edem
  • 3,222
  • 3
  • 19
  • 45
1

Since your hash keys are easily sortable, why not just sort the data once it's been received by the PHP script?

i.e.

use JSON::PP;
my %asc_array  = ( 
    "1"    => 'Introduction',
    "1.1"  => 'Scope',
    "1.2"  => 'Purpose',
    "2"    => 'Terminology',
    "2.1"  => 'Definitions',
    "2.2"  => 'Service Primitives',
    "2.3"  => 'Abbreviations',
    "2.4"  => 'Acronyms',
);

my $json = JSON::PP->new;
print $json->encode(\%asc_array);

Then, in your PHP script:

# replace this with whatever method you're using to get your JSON
# I've jumbled up the order to demonstrate the power of sorting.
$json = '{"2.3":"Abbreviations", "2.1":"Definitions", "1":"Introduction", "2.4":"Acronyms", "1.1":"Scope", "2":"Terminology", "2.2":"Service Primitives", "1.2":"Purpose"}';

$decoded = json_decode( $json, true );
ksort($decoded);

print_r($decoded);

Output:

Array
(
    [1] => Introduction
    [1.1] => Scope
    [1.2] => Purpose
    [2] => Terminology
    [2.1] => Definitions
    [2.2] => Service Primitives
    [2.3] => Abbreviations
    [2.4] => Acronyms
)
i alarmed alien
  • 9,412
  • 3
  • 27
  • 40