Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re^2: Preserve the order in JSON

by Deven (Novice)
on Sep 11, 2023 at 07:11 UTC ( [id://11154364]=note: print w/replies, xml ) Need Help??


in reply to Re: Preserve the order in JSON
in thread Preserve the order in JSON

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) };

Replies are listed 'Best First'.
Re^3: Preserve the order in JSON
by Discipulus (Canon) on Sep 11, 2023 at 07:35 UTC
    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.
Re^3: Preserve the order in JSON
by tobyink (Canon) on Sep 11, 2023 at 15:38 UTC

    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 }
Re^3: Preserve the order in JSON
by LanX (Saint) on Sep 11, 2023 at 08:14 UTC
    > 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". ;-)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (3)
As of 2024-04-21 04:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found