dmeranda / demjson

Python module for JSON data encoding, including jsonlint. See the project Wiki here on Github. Also read the README at the bottom of this page, or the project homepage at
http://deron.meranda.us/python/demjson/
Other
302 stars 76 forks source link

Insertion order of (key: value) pairs not preserved with ordered dictionary when using encode_to_file #14

Closed Kounavi closed 9 years ago

Kounavi commented 9 years ago

I've been trying to find a way for demjson to output it's (key, value) pairs in a file in the order they were inserted but that seems rather impossible even when using an OrderedDictionary.

Sample code:

opts.json_packer_builders = (OrderedDict());
opts.json_packer_builders.update({"type": "virtualbox-iso"});
opts.json_packer_builders.update({"guest_os_type": "RedHat_64"});
opts.json_packer_builders.update({"iso_url": opts.image_file_path});
opts.json_packer_builders.update({"iso_checksum": opts.image_hash_value});
opts.json_packer_builders.update({"iso_checksum_type": opts.image_hash_type});
opts.json_packer_root = (OrderedDict());
opts.json_packer_root.update({"builders": ([opts.json_packer_builders])});
demjson.encode_to_file(json_img_template, opts.json_packer_root, 
                                      overwrite = True, compactly = False, indent_amount = 3);

Output:

{  "builders" : [  {  
            "guest_os_type" : "RedHat_64",
            "iso_checksum" : "4ed6c56d365bd3ab12cd88b8a480f4a62e7c66d2",
            "iso_checksum_type" : "sha1",
            "iso_url" : "filepath",
            "type" : "virtualbox-iso"
         } ] }

Expected output:

{  "builders" : [  {  
            "type" : "virtualbox-iso"
            "guest_os_type" : "RedHat_64",
            "iso_url" : "filepath",
            "iso_checksum" : "4ed6c56d365bd3ab12cd88b8a480f4a62e7c66d2",
            "iso_checksum_type" : "sha1",
         } ] }

where

filepath
is a variable user filepath :) ;)

It's not a major issue but is there any way to do that using demjson?

dmeranda commented 9 years ago

Yes you can. There is an option, sort_keys, which you may provide to either the decode() or encode() function, or wrappers like encode_to_file().

Use sort_keys=demjson.SORT_PRESERVE to keep the same order. On decode()-ing it will create OrderedDict instances, on encoding it will preserve the order in an OrderedDicts. You can see an example of this in the included self test code (file "test/test_demjson.py"):

def testEncodeDictPreserveSorting(self):
        import collections
        d = collections.OrderedDict()
        d['X'] = 42
        d['A'] = 99
        d['Z'] = 50
        self.assertEqual(demjson.encode( d, sort_keys=demjson.SORT_PRESERVE ),
                         '{"X":42,"A":99,"Z":50}')

The various choices are:

There are many many different options that you can provide, not all of which are documented directly in the encode() function's help/docstring. Instead look at the documentation for the "json_options" class — See to 'sort_keys' descriptor (not method): http://deron.meranda.us/python/demjson/demjson-2.2.3/docs/demjson.html#json_options

Did this solve your problem?

Kounavi commented 9 years ago

Yay! Thanks! Indeed, that did the trick :) Thanks a lot for the immediate response & all the available options for that matter. Much appreciated! :]