OK. My ordering()
function was buggy. This is better:
# Human-friendly and git-friendly (deterministically diffable) JSON encoding.
from java.util import TreeMap
from com.inductiveautomation.ignition.common.util import Comparators
from com.inductiveautomation.ignition.common.gson import GsonBuilder
ciAlnumCmp = Comparators.alphaNumeric(False)
# Deep copy with conversion of maps to key-ordered maps and
# conversion of lists-of-dicts that contain a 'name' key into
# ordered lists.
# Keys other than "name" may be supplied, or None to disable
# re-ordering lists of dictionaries.
def ordering(subject, listKey='name'):
if hasattr(subject, 'items'):
subst = TreeMap(ciAlnumCmp)
for k, v in subject.items():
subst[k] = ordering(v)
return subst
if hasattr(subject, '__iter__'):
# Use a generator to exit quickly if any element of the
# list-like object is *not* a dictionary-like object.
if listKey and all(hasattr(inner, 'items') for inner in subject):
reordered = TreeMap(ciAlnumCmp)
reordered.update([(x.get(listKey, str(i)), ordering(x)) for (i, x) in enumerate(subject)])
return reordered.values()
return [ordering(x) for x in subject]
return subject
#
#
def orderedJson(source):
json = system.util.jsonDecode(source)
ordered = ordering(json)
gson = GsonBuilder().setPrettyPrinting().create()
return gson.toJson(ordered)
#
def test():
original = {'a8': 0.9, 'a9': 1, 'A10': 1.1, 'A12':1.2, 'a11': [4, 5, 6]}
ordered = jsonUtil.ordering(original)
print "Ordered:"
print repr(ordered)
print "Using system.util.jsonEncode():"
print system.util.jsonEncode(dict(_=ordered), 2)[6:-1]
print "Using Gson:"
gson = GsonBuilder().setPrettyPrinting().create()
print gson.toJson(ordered)
#
Running someScript.test()
in the script console yields this:
Ordered:
{u'a8': 0.9, u'a9': 1, u'A10': 1.1, u'a11': [4, 5, 6], u'A12': 1.2}
Using system.util.jsonEncode():
{
"A10": 1.1,
"A12": 1.2,
"a11": [
4,
5,
6
],
"a8": 0.9,
"a9": 1
}
Using Gson:
{
"a8": 0.9,
"a9": 1,
"A10": 1.1,
"a11": [
4,
5,
6
],
"A12": 1.2
}
>>>
Much better.
Also lets you disable list re-ordering, or use a different key.