FWIW, I made a script recently that achieves this with JSON tag exports, and could be tweaked for many other cases (currently uses the "name" key for sorting lists of dictionaries).
# Functions designed to be called via objectScript() in UI expressions.
from java.io import File
from java.lang import System, Throwable
from java.util import TreeMap
from com.inductiveautomation.ignition.common.util import Comparators
logger = system.util.getLogger(system.util.getProjectName() + '.' + system.reflect.getModulePath())
tkCtx = system.util.toolkitCtx()
ciAlnumCmp = Comparators.alphaNumeric(True)
def ordering(subject):
if hasattr(subject, 'items'):
subst = TreeMap(ciAlnumCmp)
for k, v in subject.items():
subst[k] = ordering(v)
return subst
first = None
try:
first = subject[0]
except:
pass
try:
if first and hasattr(first, 'items'):
subst = TreeMap(ciAlnumCmp)
subst.update([(x.get('name', str(i)), ordering(x)) for (i, x) in enumerate(subject)])
return [x for x in subst.values()]
except Throwable, t:
logger.info("Java failure in ordering:", t)
except Exception, e:
logger.info("Jython failure in ordering:", system.reflect.asThrowable(e, None))
return subject
#
#
def orderedJson(source):
json = system.util.jsonDecode(source)
ordered = ordering(json)
# print repr(ordered)
return system.util.jsonEncode(dict(_=ordered), 2)[6:-1]
#
Note that ordering() is a recursive deep copy operation, where dictionary-like types are replaced with a key-ordered dictionary, and lists of dictionaries are conditionally re-ordered by their inner name keys.
The use of name for lists of dictionaries could be made an argument to make this more widely applicable.
Consider this a plea for this algorithm or similar to become the default behavior whenever Ignition writes JSON to disk or for download/export.
The client who prompted this script's creation found it effective for re-synchronizing UDT definitions from dev to prod.

