Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Preserve the order in JSON

by Anonymous Monk
on Jul 11, 2018 at 10:52 UTC ( [id://1218299]=note: print w/replies, xml ) Need Help??


in reply to Preserve the order in JSON

Interesting that so many people have asked why you would need to preserve the order of keys when in fact it would be a very useful feature. Right now I would need it to modify the configuration of some charts, they are displayed in PHP in the order they are found in the JSON which is in turn stored in a postgres text field. I would've wanted to create a plperl function to modify the chart config but it looks like I'm better off reading the config, modifying it in PHP then saving it back to the db.

Replies are listed 'Best First'.
Re^2: Preserve the order in JSON
by choroba (Cardinal) on Jul 11, 2018 at 10:57 UTC
    If you need to preserve the order, don't use "JSON object" (aka hash in Perl) as the data structure, use an array (or include an ordering attribute to the object).

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re^2: Preserve the order in JSON
by Deven (Novice) on Sep 11, 2023 at 07:11 UTC
    Every time someone says they want to preserve the order of JSON keys, people jump on them for it, saying the keys are unordered by definition and why should they want that anyway? There are use cases for this!! Take the example of a JSON configuration file that happens to be stored in a git repository. Suppose you want to modify the JSON programmatically to make a slight change. If the keys are kept in the original order, a "git diff" of the changes will show a tiny change clearly. If all the hash keys are in a new randomized order, the diff will be mostly noise and the change will be very difficult to find.

    Anyway, I came up with a good solution for this using Monkey::Patch with JSON::PP to make it use Tie::IxHash for all objects decoded from JSON. This solves the problem, allowing a JSON file to be loaded, decoded from JSON, modified, encoded into JSON again and written back to the file, without changing the key ordering at all. Just make sure you're using JSON::PP (not JSON::XS) and that the $handle variable remains in scope:

    use Monkey::Patch qw[patch_package]; # Monkey-patch JSON::PP::object() subroutine to use Tie::IxHash. my $handle = patch_package 'JSON::PP' => 'object' => sub { my $orig = shift; my %obj; tie %obj, 'Tie::IxHash' or die "tie(\%obj, 'Tie::IxHash') failed!\n"; $orig->(\%obj) };
      Hello Deven,

      nice! as side note you can force JSON::PP to always order keys alphabetically using canonical or giving it a custom order function: JSON::PP#sort_by thus avoiding monkey patching.

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      I wrote JSON::MultiValueOrdered to cope with JSON like the following:

      { "foo": 1, "bar": 2, "foo": 3 }

      If you parse the above into $data then $data->{foo} will be 3, but tied(%$data)->get('foo') in list context will return ( 1, 3 ), and if you serialize the structure, you'll get this, preserving the original order of the keys:

      { "foo": 1, "bar": 2, "foo": 3 }
      > saying the keys are unordered by definition and why should they want that anyway

      AFAIR is this disputed, because different RFC tell differently.

      JS Objects are unsorted tho and JSON stands for "JS Object Notation".

      The curlies in JS { ... } create literal objects (kind of hashes plus inheritance chain).

      Different definitions will lead to much confusion...

      Cheers Rolf
      (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
      Wikisyntax for the Monastery

        AFAIR is this disputed, because different RFC tell differently.

        It's even worse: It is not clear if object keys MUST be unique or not. They surely SHOULD be unique. Here is the entire mess: Re^4: Outputting JSON with sorted names/keys.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re^2: Preserve the order in JSON
by Anonymous Monk on Oct 21, 2020 at 03:48 UTC
    I have a reason why. I have a vim command that I use that Tidies different files. :Tidy When it's perl code, it uses the Perl::Tidy. If it's JSON, then it formats it nicely using JSON::PP. Recently I've been doing comparisons of serialized JSON data (to make sure it's formatted correctly) and it would be nice if the order was maintained when being Tidied. Performance isn't critical, it's an editor command; not used in production.
      I've been using a one-liner. json_pp -f json -t json -json_opt pretty. I may end up implementing it using Hash::Ordered
      Use the ordering/sorting feature then nobody is stopping you

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1218299]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-23 20:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found