Graham Mitchell Graham Mitchell - 1 month ago 16
JSON Question

custom JSON sort_keys order in Python

Is there any way in Python 2.6 to supply a custom key or cmp function to JSON's sort_keys?

I've got a list of dicts coming from JSON like so:

[
{
"key": "numberpuzzles1",
"url": "number-puzzle-i.html",
"title": "Number Puzzle I",
"category": "nestedloops",
"points": "60",
"n": "087"
},
{
"key": "gettingindividualdigits",
"url": "getting-individual-digits.html",
"title": "Getting Individual Digits",
"category": "nestedloops",
"points": "80",
"n": "088"
}
]


...which I've stored into the list variable
assigndb
. I'd like to be able to load in the JSON, modify it, and serialized it back out with
dumps
(or whatever), keeping the orders of the keys intact.

So far, I've tried something like this:

ordering = {'key': 0, 'url': 1, 'title': 2, 'category': 3,
'flags': 4, 'points': 5, 'n': 6}

def key_func(k):
return ordering[k]

# renumber assignments sequentially
for (i, a) in enumerate(assigndb):
a["n"] = "%03d" % (i+1)

s = json.dumps(assigndb, indent=2, sort_keys=True, key=key_func)


...but of course
dumps
doesn't support a custom key like
list.sort()
does. Something with a custom
JSONEncoder
maybe? I can't seem to get it going.

Answer

This is kind of ugly, but in case tokland's solution does not work for you:

data = [{'category': 'nestedloops', 'title': 'Number Puzzle I', 'url': 'number-puzzle-i.html', 'n': '087', 'points': '60', 'key': 'numberpuzzles1'}, {'category': 'nestedloops', 'title': 'Getting Individual Digits', 'url': 'getting-individual-digits.html', 'n': '088', 'points': '80', 'key': 'gettingindividualdigits'}]
ordering = {'key': 0, 'url': 1, 'title': 2, 'category': 3,
            'flags': 4, 'points': 5, 'n': 6}
outlist = []
for d in data:
    outlist.append([])
    for k in sorted(d.keys(), key=lambda k: ordering[k]):
        outlist[-1].append(json.dumps({k: d[k]}))

for i, l in enumerate(outlist):
    outlist[i] = "{" + ",".join((s[1:-1] for s in outlist[i])) + "}"

s = "[" + ",".join(outlist) + "]"