Skip to main content

Diffable JSON Strings

If you need a JSON object/string to be consistently ordered regardless of how it was built or ordered in memory, the following script can help force it to be organized/ordered alphabetically so that it can be used with source control tools or use diff tools to compare different outputs to one another.

# Functions designed to be called via objectScript() in UI expressions.
# Requires the Automation Toolkit by Automation Professionals (Phil Turmel)

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(json):
	'''
    Re-orders a JSON string alphabetically so it can be use with diff tools or other source control tools

	Args:
		json (str): JSON Dictionary as a string to be re-ordered

	Returns:
		str: Re-ordered JSON string
		
     '''
	source = system.util.jsonDecode(json)
	ordered = __ordering(source)

	return system.util.jsonEncode(dict(_=ordered), 2)[6:-1]

Source slightly tweaked from: https://forum.inductiveautomation.com/t/new-feature-tag-report-tool/61594/65json-diffing-discussion/96800