[IGN-10886] jsonEncode arrays with indentFactor

Has anyone has run into a bug trying to "pretty print" JSON when the object is an array?

This:

content = [{'someKey': 'someValue'}, {'anotherKey': 'anotherValue'}]
json = system.util.jsonEncode(content)
print json

Produces this:

>>> 
[{"someKey":"someValue"},{"anotherKey":"anotherValue"}]
>>>

But if you replace line 2 with this:

json = system.util.jsonEncode(content, 2)

You get this exception:

>>> 
Java Traceback:
Traceback (most recent call last):
  File "<input>", line 2, in <module>
	at org.json.JSONTokener.syntaxError(JSONTokener.java:430)
	at org.json.JSONObject.<init>(JSONObject.java:176)
	at org.json.JSONObject.<init>(JSONObject.java:294)
	at com.inductiveautomation.ignition.common.script.builtin.SystemUtilities.jsonEncode(SystemUtilities.java:441)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
org.json.JSONException: org.json.JSONException: A JSONObject text must begin with '{' at 1 [character 2 line 1]

	at org.python.core.Py.JavaError(Py.java:545)
	at org.python.core.Py.JavaError(Py.java:536)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:192)
	at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:553)
	at org.python.core.PyObject.__call__(PyObject.java:477)
	at org.python.core.PyObject.__call__(PyObject.java:481)
	at org.python.pycode._pyx42.f$0(<input>:3)
	at org.python.pycode._pyx42.call_function(<input>)
	at org.python.core.PyTableCode.call(PyTableCode.java:173)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1703)
	at org.python.core.Py.exec(Py.java:1747)
	at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:277)
	at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:130)
	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:628)
	at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:616)
	at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.desktop/javax.swing.SwingWorker.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.json.JSONException: A JSONObject text must begin with '{' at 1 [character 2 line 1]
	at org.json.JSONTokener.syntaxError(JSONTokener.java:430)
	at org.json.JSONObject.<init>(JSONObject.java:176)
	at org.json.JSONObject.<init>(JSONObject.java:294)
	at com.inductiveautomation.ignition.common.script.builtin.SystemUtilities.jsonEncode(SystemUtilities.java:441)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
	... 19 more
Traceback (most recent call last):
  File "<input>", line 2, in <module>
	at org.json.JSONTokener.syntaxError(JSONTokener.java:430)
	at org.json.JSONObject.<init>(JSONObject.java:176)
	at org.json.JSONObject.<init>(JSONObject.java:294)
	at com.inductiveautomation.ignition.common.script.builtin.SystemUtilities.jsonEncode(SystemUtilities.java:441)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
org.json.JSONException: org.json.JSONException: A JSONObject text must begin with '{' at 1 [character 2 line 1]
>>>

Also happens with arrays from document tags?

Using v8.1.39 at the moment.

I'm using this work-around at the moment, because I know I have an array:

content = [{'someKey': 'someValue'}, {'anotherKey': 'anotherValue'}]
json = system.util.jsonEncode(dict(_=content), 2)
print json[6:-1]
1 Like

I think this is just broken and always has been.

It's calling directly into a org.json.JSONObject::toString method that accepts an "indentFactor" that is by default 0, and otherwise expects the thing passed into to be an object, and looks for the opening/closing brackets.

Hmmm. Why does it work without the indentFactor?

In other words, is it fixable? (The value editor for document tags doesn't choke like this, but is similarly "pretty".)

Looking into it, I think it returns early.

I just emailed support to open a ticket for me. (Cannot login to the support site--bouncing right back from the login page. :frowning_face: )

Yeah, it needs a ticket, it's fixable.

It's basically doing this:

        String json = "[1,2,3]";
        
        System.out.println(new JSONObject(json).toString(2));

When it should do this for arrays:

        String json = "[1,2,3]";

        System.out.println(new JSONArray(json).toString(2));
4 Likes