4

My function's return value type is OrderedDict,

and now I want to write this on the file:

Here's my code:

mainDict = OrderedDict([('a',1),('b',2),('c',3),('d',[4,5,6])])
with open(outFileName, 'w', encoding='utf-8') as outFile :
   outFile.write(ujson.dumps(mainDict, indent=4))

I expected it to keep the order of the dictionary in the file, but it got mixed up.

Is it because of using ujson.dumps? and how can I keep the order of an OrderedDict in the output file?

gavv
  • 4,649
  • 1
  • 23
  • 40
sh kim
  • 183
  • 1
  • 8
  • 1
    json doesn't allow ordered dicts. From json.org: "An object is an unordered set of name/value pairs.". object is the json/javascript equivalent of a Python dict. If you want to keep the order, turn it into a list (json array). –  Jul 06 '16 at 03:23
  • @Evert, The output order is decided by dict itself, json does not care about it. What json does is calling dict.items() for formatting. OrderedDict.items() which is ordered-aware. – Jacky1205 Jul 06 '16 at 03:41
  • @sh kim In my side, the output is ordered with `json`. What is ujson, does it equal to json? – Jacky1205 Jul 06 '16 at 03:42
  • Why do you need to keep the order, what do you do with the json file? – Bi Rico Jul 06 '16 at 03:55
  • @Jacky I heard `json` and `ujson` modules are similar so I use `ujson` without reason.. and like your mention, I just change `ujson` to `json` in my code, then it worked!!! my outfile keeps order I made!!! thanks – sh kim Jul 06 '16 at 05:03
  • @BiRico usually json file don't need order but these files contain informations of projects and sometimes I have to check this roughly so I wanted to make readable file. – sh kim Jul 06 '16 at 07:36

3 Answers3

5

Use sort_keys parameter of ujson.dumps

Behaviour of ujson is the following:

  • sort_keys=None (default if omitted) - dump dict keys in implementation-defined order, which may be different every launch (but it's fast)
  • sort_keys=True - sort dict keys before dump
  • sort_keys=False - preserve dict keys order provided by dict.items()

So to preserve ordering of OrderedDict with ujson, you need sort_keys=False.


Tests

This is how you can check it:

import sys
import ujson

order = None
if len(sys.argv) == 2:
    order = bool(int(sys.argv[1]))

mainDict = OrderedDict([('c',3),('b',2),('a',1)])
sys.stdout.write(ujson.dumps(mainDict, sort_keys=order))

Tests:

$ python order.py      # sort_keys=None
{"c":3,"a":1,"b":2}

$ python order.py      # sort_keys=None
{"b":2,"c":3,"a":1}

$ python order.py 1    # sort_keys=True
{"a":1,"b":2,"c":3}

$ python order.py 0    # sort_keys=False
{"c":3,"b":2,"a":1}

Notes

Note that unlike ujson, built-in json module preserves key order with sort_keys=None, as well as with sort_keys=False.

Also note that although it's possible to preserve keys order with these implementations (ujson and json), it's non-standard JSON. See json.org:

An object is an unordered set of name/value pairs.

gavv
  • 4,649
  • 1
  • 23
  • 40
  • Unfortunately, this does not work as expected, due to a bug in the ujson library [https://github.com/esnme/ultrajson/issues/250]. Bug has been claimed to be fixed but not released in a new version since (2 years now!). – odedfos Apr 07 '19 at 09:10
0

Use like this

mainDict = OrderedDict([('a',1),('b',2),('c',3),('d',[4,5,6])])
with open(outFileName, 'w', encoding='utf-8') as outFile :
   outFile.write(ujson.dumps(mainDict, indent=4, sort_keys=False))
Rakesh Kumar
  • 4,319
  • 2
  • 17
  • 30
-1

Yes, it seems like ujson dumps the dictionary as an unordered dictionary by default, unlike the built-in json package. Set the sort_keys argument to true to dump the data as an ordered dictionary.

Here's my the sample code:

import ujson
import json
from collections import OrderedDict

mainDict = OrderedDict([('a',1),('b',2),('c',3),('d',[4,5,6])])

# Maintain the ordering of dictionary upon dump.
with open("ordereddict2.txt", 'w') as outFile :
  outFile.write(ujson.dumps(mainDict, indent=4, sort_keys=True))
b4oshany
  • 692
  • 1
  • 7
  • 15
  • 1
    `sort_keys` sorts the input, it doesn't preserve its state. Try this, `json.dumps(OrderedDict([('b','b'), ('a','a')]), sort_keys=True)`. – Bi Rico Jul 07 '16 at 21:09
  • Note, with json.dumps, you don't have to use `sort_keys=True` if the current state of the dictionary is in the order that you want. – b4oshany Jul 08 '16 at 11:01
  • "Without the sort_keys set to True, the dictionary will loose its order upon dump." -- this is incorrect, see my answer – gavv Jul 08 '16 at 11:30
  • Please read what I wrote carefully. My answer is correct. I did state with `ujson` you must use `sort_keys`. However, if u already sorted the json, you can use `json` without the `sort_keys`. – b4oshany Jul 08 '16 at 13:37