makamaka / JSON

perl implementation of JSON encoder/decoder
42 stars 40 forks source link

$jsonObj->pretty->encode($tempAA{'attr'} seems to return sub elements in random order - please advise how to get sorted list of elements #58

Closed robbinmav closed 1 month ago

robbinmav commented 2 months ago

version: PERLBREW_PATH: /root/perl5/perlbrew/bin:/root/perl5/perlbrew/perls/perl-5.36.0/bin PERLBREW_MANPATH: /root/perl5/perlbrew/perls/perl-5.36.0/man

Module: JSON Location: /root/perl5/perlbrew/perls/perl-5.36.0/lib/site_perl/5.36.0/JSON.pm Version: 4.10

Module: JSON::MaybeXS Location: /root/perl5/perlbrew/perls/perl-5.36.0/lib/site_perl/5.36.0/JSON/MaybeXS.pm Version: 1.004004

Module: JSON::Parse Location: /root/perl5/perlbrew/perls/perl-5.36.0/lib/site_perl/5.36.0/x86_64-linux/JSON/Parse.pm Version: 0.62

Module: JSON::XS Location: /root/perl5/perlbrew/perls/perl-5.36.0/lib/site_perl/5.36.0/x86_64-linux/JSON/XS.pm Version: 4.03

Module: Test::Deep::JSON Location: /root/perl5/perlbrew/perls/perl-5.36.0/lib/site_perl/5.36.0/Test/Deep/JSON.pm Version: 0.05

Sample code used to demonstrate the problem. original JSON: {"attr":{"remote":"str1","uuid":{"uuid":{"$uuid":"a1"}},"connectionId":16,"connectionCount":1} }

in each case the tags in the original JSON have the same order. the JSON is read using this code:

`` my (%tempAA) = (); my($tempJsonAARef) = undef; try { $tempJsonAARef = fromjson($line); } catch { if ( $ =~ /malformed JSON string/ ) {

print STDERR PACKAGE." ".LINE." No JSON content in line: $line error: $\n" if $ =~ /malformed JSON string/;

    } else
    {
        print STDERR __PACKAGE__." ".__LINE__."  Error when processing from_json error: $_\n";
    }
};
%tempAA = %$tempJsonAARef if ref($tempJsonAARef) eq "HASH";

my ($jsonObj) = JSON->new->allow_nonref;
my ($prettyStr) = $jsonObj->pretty->encode($tempAA{'attr'});

The pretty print output below shows the structure of the hash

pretty print version of the hash 'Connection accepted { 'uuid' : { 'uuid' : { '$uuid' : 'a1' } }, 'remote' : 'str1', 'connectionCount' : 1, 'connectionId' : 16 } ``

in this example the ids are listed in the following order: uuid, remote, connectionCount, connectionId

in the examples below the {. indicates where the carriage returns have been stripped out.

'Connection accepted {. 'uuid' : {. 'uuid' : {. '$uuid' : 'a2'. }. },. 'connectionId' : 17,. 'connectionCount' : 1,. 'remote' : 'str2'.}.

order here is: in this example the ids are listed in the following order: uuid, connectionId, connectionCount, remote

'Connection accepted {. 'uuid' : {. 'uuid' : {. '$uuid' : 'a3'. }. },. 'connectionId' : 18,. 'remote' : 'str3',. 'connectionCount' : 1.}.

in this example the ids are listed in the following order: uuid, connectionId, remote, connectionCount

'Connection accepted {. 'uuid' : {. 'uuid' : {. '$uuid' : 'a4'. }. },. 'connectionCount' : 1,. 'remote' : 'str4',. 'connectionId' : 19.}.

in this example the ids are listed in the following order: uuid, connectionCount, remote, connectionId

In my case the pretty print text is logged a single string so the users can review them. However it isn't possible to look at the entries and immediately see if the values of the fields are different because the order is different in every case.

In some cases the comparisons could be performed by the user in a non-Perl environment e.g. Excel.

== I understand that changing the existing code would risk breaking existing code.

The request is to provide a method / option that allows the order of the keys to be defined e.g. the keys must be sorted. It appears that the values are being retrieved from the hash in a random order. adding the option to return the keys in a sorted order would add a lot of value when performing comparisons.

If I have missed a setting/misunderstood how to use this then please advise me on how to change my code to get the desired results.

thanks

charsbar commented 2 months ago

https://metacpan.org/pod/JSON#canonical ?

robbinmav commented 1 month ago

Thanks., I thought I had gone through all the options but I missed that one. I have implemented it and it works as expected.