diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83da486..2b4f911 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,6 +49,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2. [For loops in RemesPath](/docs/RemesPath.md#for-loopsloop-variables-added-in-v60)
3. [`bool, s_csv` and `s_fa` vectorized arg functions](/docs/RemesPath.md#vectorized-functions) and [`randint` non-vectorized arg function](/docs/RemesPath.md#non-vectorized-functions) to RemesPath.
4. Make second argument of [`s_split` RemesPath function](/docs/RemesPath.md#vectorized-functions) optional; 1-argument variant splits on whitespace.
+5. Right-click dropdown menu in [error form](/docs/README.md#error-form-and-status-bar), allowing export of errors to JSON or refreshing the form.
+6. The parser is now much better at recovering when an object is missing its closing `'}'` or an array is missing its closing `']'`.
### Changed
diff --git a/JsonToolsNppPlugin/Forms/ErrorForm.Designer.cs b/JsonToolsNppPlugin/Forms/ErrorForm.Designer.cs
index d1eaa30..9e1233c 100644
--- a/JsonToolsNppPlugin/Forms/ErrorForm.Designer.cs
+++ b/JsonToolsNppPlugin/Forms/ErrorForm.Designer.cs
@@ -28,12 +28,17 @@ protected override void Dispose(bool disposing)
///
private void InitializeComponent()
{
+ this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ErrorForm));
this.ErrorGrid = new System.Windows.Forms.DataGridView();
this.Severity = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Description = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Position = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.errorGridRightClickStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.refreshMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exportToJsonMenuItem = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)(this.ErrorGrid)).BeginInit();
+ this.errorGridRightClickStrip.SuspendLayout();
this.SuspendLayout();
//
// ErrorGrid
@@ -55,6 +60,7 @@ private void InitializeComponent()
this.ErrorGrid.CellEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.ErrorGrid_CellEnter);
this.ErrorGrid.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.ErrorGrid_CellEnter);
this.ErrorGrid.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ErrorForm_KeyDown);
+ this.ErrorGrid.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ErrorForm_RightClick);
this.ErrorGrid.Resize += new System.EventHandler(this.ErrorGrid_Resize);
//
// Severity
@@ -81,6 +87,29 @@ private void InitializeComponent()
this.Position.ReadOnly = true;
this.Position.Width = 75;
//
+ // errorGridRightClickStrip
+ //
+ this.errorGridRightClickStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
+ this.errorGridRightClickStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.refreshMenuItem,
+ this.exportToJsonMenuItem});
+ this.errorGridRightClickStrip.Name = "errorGridRightClickStrip";
+ this.errorGridRightClickStrip.Size = new System.Drawing.Size(252, 80);
+ //
+ // refreshMenuItem
+ //
+ this.refreshMenuItem.Name = "refreshMenuItem";
+ this.refreshMenuItem.Size = new System.Drawing.Size(251, 24);
+ this.refreshMenuItem.Text = "Refresh with current errors";
+ this.refreshMenuItem.Click += new System.EventHandler(this.RefreshMenuItem_Click);
+ //
+ // exportToJsonMenuItem
+ //
+ this.exportToJsonMenuItem.Name = "exportToJsonMenuItem";
+ this.exportToJsonMenuItem.Size = new System.Drawing.Size(190, 24);
+ this.exportToJsonMenuItem.Text = "Export to JSON";
+ this.exportToJsonMenuItem.Click += new System.EventHandler(this.ExportLintsToJsonMenuItem_Click);
+ //
// ErrorForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
@@ -92,6 +121,7 @@ private void InitializeComponent()
this.Text = "Syntax errors in JSON";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ErrorForm_KeyDown);
((System.ComponentModel.ISupportInitialize)(this.ErrorGrid)).EndInit();
+ this.errorGridRightClickStrip.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -101,5 +131,8 @@ private void InitializeComponent()
private System.Windows.Forms.DataGridViewTextBoxColumn Description;
private System.Windows.Forms.DataGridViewTextBoxColumn Position;
private System.Windows.Forms.DataGridView ErrorGrid;
+ private System.Windows.Forms.ContextMenuStrip errorGridRightClickStrip;
+ private System.Windows.Forms.ToolStripMenuItem refreshMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exportToJsonMenuItem;
}
}
\ No newline at end of file
diff --git a/JsonToolsNppPlugin/Forms/ErrorForm.cs b/JsonToolsNppPlugin/Forms/ErrorForm.cs
index 1f3d0cc..e016592 100644
--- a/JsonToolsNppPlugin/Forms/ErrorForm.cs
+++ b/JsonToolsNppPlugin/Forms/ErrorForm.cs
@@ -11,6 +11,7 @@
using Kbg.NppPluginNET;
using JSON_Tools.JSON_Tools;
using JSON_Tools.Utils;
+using System.Runtime;
namespace JSON_Tools.Forms
{
@@ -137,6 +138,47 @@ private void ChangeSelectedRow(int oldIndex, int newIndex)
HandleCellOrRowClick(newRow); // move to location of error
}
+ ///
+ /// right-clicking the grid shows a drop-down where the user can choose to refresh the form or export the lints as JSON.
+ ///
+ private void ErrorForm_RightClick(object sender, MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Right)
+ {
+ errorGridRightClickStrip.Show(MousePosition);
+ }
+ }
+
+ private void RefreshMenuItem_Click(object sender, EventArgs e)
+ {
+ Npp.notepad.HideDockingForm(this);
+ Main.OpenErrorForm(Npp.notepad.GetCurrentFilePath(), false);
+ }
+
+ private void ExportLintsToJsonMenuItem_Click(object sender, EventArgs e)
+ {
+ int lintCount = lints == null ? 0 : lints.Count;
+ if (lintCount == 0)
+ {
+ MessageBox.Show($"No JSON syntax errors (at or below {Main.settings.logger_level} level) for {fname}",
+ "No JSON syntax errors for this file",
+ MessageBoxButtons.OK, MessageBoxIcon.Information);
+ return;
+ }
+ var lintArrChildren = new List();
+ foreach (JsonLint lint in lints)
+ {
+ var lintObj = lint.ToJson();
+ lintArrChildren.Add(lintObj);
+ }
+ var lintArr = new JArray(0, lintArrChildren);
+ Main.PrettyPrintJsonInNewFile(lintArr);
+ }
+
+ ///
+ /// hitting enter refreshes
+ /// hitting the first letter of any error description goes to that error description
+ ///
private void ErrorForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
diff --git a/JsonToolsNppPlugin/Forms/ErrorForm.resx b/JsonToolsNppPlugin/Forms/ErrorForm.resx
index e627d24..d11fc5c 100644
--- a/JsonToolsNppPlugin/Forms/ErrorForm.resx
+++ b/JsonToolsNppPlugin/Forms/ErrorForm.resx
@@ -126,6 +126,18 @@
True
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 17, 17
+
diff --git a/JsonToolsNppPlugin/JSONTools/JsonParser.cs b/JsonToolsNppPlugin/JSONTools/JsonParser.cs
index 16d5c42..5ee574a 100644
--- a/JsonToolsNppPlugin/JSONTools/JsonParser.cs
+++ b/JsonToolsNppPlugin/JSONTools/JsonParser.cs
@@ -7,6 +7,7 @@
using System.Text;
using System.Text.RegularExpressions;
using JSON_Tools.Utils;
+using static System.Windows.Forms.LinkLabel;
namespace JSON_Tools.JSON_Tools
{
@@ -74,6 +75,19 @@ public static string CharDisplay(char c)
default: return $"'{c}'";
}
}
+
+ ///
+ /// the object {"message": this.message, "position": this.pos, "severity": this.severity}
+ ///
+ public JNode ToJson()
+ {
+ return new JObject(0, new Dictionary
+ {
+ ["message"] = new JNode(message),
+ ["position"] = new JNode((long)pos),
+ ["severity"] = new JNode(severity.ToString()),
+ });
+ }
}
///
@@ -762,9 +776,9 @@ public string ParseKey(string inp)
public string ParseUnquotedKey(string inp)
{
var match = UNQUOTED_KEY_REGEX.Match(inp, ii);
- if (!match.Success)
+ if (!match.Success || match.Index != ii)
{
- HandleError($"No valid unquoted key beginning at {ii}", inp, ii, ParserState.FATAL);
+ HandleError($"No valid unquoted key beginning at {ii}", inp, ii, ParserState.BAD);
return null;
}
HandleError("Unquoted keys are only supported in JSON5", inp, ii, ParserState.JSON5);
@@ -1120,7 +1134,17 @@ public JArray ParseArray(string inp, int recursionDepth)
// a new array member of some sort
alreadySeenComma = false;
JNode newObj;
+ int iiBeforeParse = ii;
+ int utf8ExtraBeforeParse = utf8ExtraBytes;
newObj = ParseSomething(inp, recursionDepth);
+ if (newObj.type == Dtype.STR && ii < inp.Length && inp[ii] == ':')
+ {
+ // maybe the user forgot the closing ']' of an array that's the child of an object.
+ HandleError("':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?", inp, ii, ParserState.BAD);
+ ii = iiBeforeParse;
+ utf8ExtraBytes = utf8ExtraBeforeParse;
+ return arr;
+ }
//if (includeExtraProperties)
//{
// newObj.extras = new ExtraJNodeProperties(arr, ii, children.Count);
@@ -1212,9 +1236,13 @@ public JObject ParseObject(string inp, int recursionDepth)
return obj;
}
// a new key-value pair
+ int iiBeforeKey = ii;
+ int utf8ExtraBeforeKey = utf8ExtraBytes;
string key = ParseKey(inp);
if (fatal || key == null)
{
+ // key could be null if there's a valid JSON there that is not a valid key
+ // this covers the possibility that the user forgot to close the object before this (presumed) key, and in fact it's meant to be a value in a parent array
return obj;
}
if (ii >= inp.Length)
@@ -1233,10 +1261,20 @@ public JObject ParseObject(string inp, int recursionDepth)
{
break;
}
- if (inp[ii] == ':')
+ char c = inp[ii];
+ if (c == ':')
{
ii++;
}
+ else if (c == ',' || c == ']')
+ {
+ // comma or ']' after key instead of value could mean that this is supposed to be a value in a parent array,
+ // so we'll try bailing out here and reinterpreting the key as such
+ HandleError($"Found '{c}' after key {childCount} when colon expected", inp, ii, ParserState.BAD);
+ ii = iiBeforeKey;
+ utf8ExtraBytes = utf8ExtraBeforeKey;
+ return obj;
+ }
else HandleError($"No ':' between key {childCount} and value {childCount} of object", inp, ii, ParserState.BAD);
}
if (!ConsumeInsignificantChars(inp))
@@ -1376,7 +1414,7 @@ public JNode ParseSomething(string inp, int recursionDepth)
inp, ii + 1, ParserState.FATAL);
return new JNode(null, Dtype.NULL, startUtf8Pos);
}
- HandleError("Badly located character", inp, ii, ParserState.FATAL);
+ HandleError("Badly located character " + (ii >= inp.Length ? "\"\\x00\"" : JNode.StrToString(inp.Substring(ii, 1), true)), inp, ii, ParserState.FATAL);
return new JNode(null, Dtype.NULL, startUtf8Pos);
}
diff --git a/JsonToolsNppPlugin/Main.cs b/JsonToolsNppPlugin/Main.cs
index 4818902..052e0e9 100644
--- a/JsonToolsNppPlugin/Main.cs
+++ b/JsonToolsNppPlugin/Main.cs
@@ -1112,7 +1112,7 @@ private static void RestyleEverything()
///
///
///
- private static void OpenErrorForm(string fname, bool wasAutoTriggered)
+ public static void OpenErrorForm(string fname, bool wasAutoTriggered)
{
bool wasVisible = errorForm != null && errorForm.Visible;
if ((!TryGetInfoForFile(fname, out JsonFileInfo info)
diff --git a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs
index bc19eea..65a8b98 100644
--- a/JsonToolsNppPlugin/Properties/AssemblyInfo.cs
+++ b/JsonToolsNppPlugin/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@
// Build Number
// Revision
//
-[assembly: AssemblyVersion("5.8.0.11")]
-[assembly: AssemblyFileVersion("5.8.0.11")]
+[assembly: AssemblyVersion("5.8.0.12")]
+[assembly: AssemblyFileVersion("5.8.0.12")]
diff --git a/JsonToolsNppPlugin/Tests/JsonParserTests.cs b/JsonToolsNppPlugin/Tests/JsonParserTests.cs
index 4d50f72..b287164 100644
--- a/JsonToolsNppPlugin/Tests/JsonParserTests.cs
+++ b/JsonToolsNppPlugin/Tests/JsonParserTests.cs
@@ -769,11 +769,11 @@ public static bool TestLinter()
new string[]{ "NaN is not part of the original JSON specification",
"Infinity is not part of the original JSON specification",
"Infinity is not part of the original JSON specification" }),
- ("{'a\n':[1,2,},]", "{\"a\\n\": [1,2]}", new string[]{"Singlequoted strings are only allowed in JSON5", "Object key contains newline", "Tried to terminate an array with '}'", "Comma after last element of array", "Tried to terminate object with ']', Comma after last key-value pair of object" }),
+ ("{'a\n':[1,2,},]", "{\"a\\n\": [1,2]}", new string[]{"Singlequoted strings are only allowed in JSON5", "Object key contains newline", "Tried to terminate an array with '}'", "Comma after last element of array", "Tried to terminate object with ']'", "Comma after last key-value pair of object" }),
("[1, 2", "[1, 2]", new string[]{ "Unterminated array" }),
("{\"a\": 1", "{\"a\": 1}", new string[]{ "Unterminated object" }),
("{\"a\": [1, {\"b\": 2", "{\"a\": [1, {\"b\": 2}]}", new string[] { "Unterminated object",
- "Unterminated array",
+ "Unterminated array",
"Unterminated object" }),
("{", "{}", new string[] { "Unterminated object" }),
("[", "[]", new string[] { "Unterminated array" }),
@@ -809,7 +809,7 @@ public static bool TestLinter()
("froeu", "null", new string[]{"Expected literal starting with 'f' to be false"}),
("Froeu", "null", new string[]{"Expected literal starting with 'F' to be False"}),
("nurnoe", "null",new string[]{"Expected literal starting with 'n' to be null or nan"}),
- ("Hugre", "null", new string[]{"Badly located character"}),
+ ("Hugre", "null", new string[]{"Badly located character \"H\""}),
("[undefined, underpants]", "[null, null]",
new string[]{
"undefined is not part of any JSON specification",
@@ -914,6 +914,64 @@ public static bool TestLinter()
}),
("0xFFFFFFFFFFFFFFFFFFFFFFFFFFF", "null", new string[]{ "Hexadecimal numbers are only part of JSON5", "Hex number too large for a 64-bit signed integer type"}),
("-0xFFFFFFFFFFFFFFFFFFFFFFFFFFF", "null", new string[]{ "Hexadecimal numbers are only part of JSON5", "Hex number too large for a 64-bit signed integer type"}),
+ ("{\"a\": [[1, 2], [3, 4, \"b\": [5 , \"c\": [, \"d\": 6}", "{\"a\": [[1, 2], [3, 4]], \"b\": [5], \"c\": [], \"d\": 6}",
+ new string[]{ "':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?",
+ "No comma between array members",
+ "':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?",
+ "No comma after key-value pair 0 in object",
+ "':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?",
+ "No comma after key-value pair 1 in object",
+ "Comma before first value in array",
+ "':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?",
+ "No comma after key-value pair 2 in object"}
+ ),
+ ( "[{\"a\": 0, null" + // seeing the 2 where a key was expected triggers falling out of the object
+ ", {2" + // we fall out of the empty object upon seeing this invalid key
+ ", {,3" + // we fall out of the empty object upon seeing the comma
+ ", {\"b\": [4, 5," +
+ " {\"c\": 6, \"d\" ]}" + // seeing this ']' instead of a colon triggers falling out of the object, and reinterpreting the "d" as a member of the parent array
+ ", {\"e\": {" +
+ " \"f\": [null, \"g\": {" + // seeing the colon after "g" triggers falling out of the array, and reinterpreting the "g" as a key of the parent object
+ " \"h\": 7, \"i\"" + // seeing this comma instead of a colon triggers falling out of the object (and its parent object, and its grandparent object), and finally reinterpreting the "i" as a child of the great-grandparent array
+ ", \"j\"]",
+ "[{\"a\": 0}, null, {}, 2, {}, 3, {\"b\": [4, 5, {\"c\": 6}, \"d\"]}, {\"e\": {\"f\": [null], \"g\": {\"h\": 7}}}, \"i\", \"j\"]",
+ new string[]{
+ "Unquoted keys are only supported in JSON5",
+ "Found ',' after key 1 when colon expected",
+ "No comma between array members",
+ "No valid unquoted key beginning at 17",
+ "No comma between array members",
+ "Comma before first value in object",
+ "No valid unquoted key beginning at 22",
+ "No comma between array members",
+ "Found ']' after key 1 when colon expected",
+ "No comma between array members",
+ "':' (key-value separator) where ',' between array members expected. Maybe you forgot to close the array?",
+ "No comma after key-value pair 0 in object",
+ "Found ',' after key 1 when colon expected",
+ "No comma after key-value pair 1 in object",
+ "Found ',' after key 2 when colon expected",
+ "No comma after key-value pair 0 in object",
+ "Found ',' after key 1 when colon expected",
+ "No comma between array members"
+ }
+ ),
+ (
+ "[ \r\n" +
+ " {\"foo\": 1, \"bar\": [\"a\", \"b\"},\r\n" + // missing close ']' of array
+ " {\"foo\": 2, \"bar\": [\"c\", \"d\"]},\r\n" + // at the start of this object, the parser thinks it's parsing the last array
+ // however, when it tries to parse the '{' opening this object as a key, it fails, and falls back into the parent array
+ // once the parser has fallen through to the parent array, everything is fine.
+ " {\"foo\": 3, \"bar\": [\"e\", \"f\"]}\r\n" + // also fine
+ "]",
+ "[{\"foo\": 1, \"bar\": [\"a\", \"b\"]}, {\"foo\": 2, \"bar\": [\"c\", \"d\"]}, {\"foo\": 3, \"bar\": [\"e\", \"f\"]}]",
+ new string[]
+ {
+ "Tried to terminate an array with '}'",
+ "No valid unquoted key beginning at 43",
+ "No comma between array members"
+ }
+ ),
};
int tests_failed = 0;
@@ -929,7 +987,7 @@ public static bool TestLinter()
continue;
}
JNode result = new JNode();
- string expected_lint_str = "[" + string.Join(", ", expected_lint) + "]";
+ string expected_lint_str = "[" + string.Join(", ", expected_lint.Select(x => JNode.StrToString(x, true))) + "]";
string base_message = $"Expected JsonParser(LoggerLevel.STRICT).Parse({inp})\nto return\n{desired_out} and have lint {expected_lint_str}\n";
try
{
@@ -944,7 +1002,7 @@ public static bool TestLinter()
lint_sb.Append('[');
for (int jj = 0; jj < parser.lint.Count; jj++)
{
- lint_sb.Append(parser.lint[jj].message);
+ lint_sb.Append(JNode.StrToString(parser.lint[jj].message, true));
if (jj < parser.lint.Count - 1) lint_sb.Append(", ");
}
lint_sb.Append("]");
diff --git a/docs/README.md b/docs/README.md
index 2d1954c..59d7027 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -100,7 +100,7 @@ Error reporting can be customized with the `logger_level` setting, which has 5 l
* Python-style '#' comments
* Python constants `None`, *`nan`, and `inf` (starting in [5.4.0](/CHANGELOG.md#540---2023-07-04))*.
* missing commas between array members
- * missing ']' or '}' at the ends of arrays and objects
+ * missing ']' or '}' at the ends of arrays and objects (supported for a long time, but *JsonTools got much better at this beginning in [v6.0](/CHANGELOG.md#600---unreleased-2023-mm-dd)*)
* a bunch of other common syntax errors
6. __FATAL__: These errors always cause *immediate failure* of parsing. Examples include:
* unquoted string literals other than `true`, `false`, `null`, `NaN`, `Infinity`, `None`, `True`, `False`, `nan`, `inf` and `undefined`.
@@ -167,6 +167,8 @@ Clicking on or paging to a row in the error form with the arrow keys will move t
Hitting `Enter` while in the form refreshes the form with the JSON in the current document. You can also seek the next syntax error with a description that starts with a letter by typing that letter while in the form. For example, typing `P` in the form might select the next `Python-style '#' comments are not part of any well-accepted JSON specification` error.
+Beginning in [v6.0](/CHANGELOG.md#600---unreleased-2023-mm-dd), you can right-click on this form to gain the option of exporting all errors to JSON or refreshing the form.
+
In addition to this form, the document type status bar section will show how many errors were logged.
![Error form and description in status bar](/docs/error%20form%20and%20status%20bar%20section.PNG)
@@ -654,7 +656,7 @@ Here's an example of what you get with successful request(s):
The URLs of successful requests show up in the box on the right. I used the `View results in buffer` button at the bottom of the form to open the buffer and tree view shown here.
-Of course, sometimes an API request will fail. You can click the [View errors button](#viewing-errors) to see any errors that happened.
+Of course, sometimes an API request will fail. You can click the [View errors button](#error-form-and-status-bar) to see any errors that happened.
## Getting JSON from local directories ##
diff --git a/most recent errors.txt b/most recent errors.txt
index eeabd1a..6a785ab 100644
--- a/most recent errors.txt
+++ b/most recent errors.txt
@@ -1,4 +1,4 @@
-Test results for JsonTools v5.8.0.10 on Notepad++ 8.5.8 64bit
+Test results for JsonTools v5.8.0.12 on Notepad++ 8.5.8 64bit
NOTE: Ctrl-F (regular expressions *on*) for "Failed [1-9]\d*" to find all failed tests
Tests failed: YAML dumper
=========================
@@ -40,7 +40,7 @@ Testing JSON parser's linter
=========================
Failed 0 tests.
-Passed 57 tests.
+Passed 60 tests.
=========================
Testing JSON Lines parser
=========================
@@ -202,33 +202,33 @@ Testing JsonParser performance
Preview of json: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c"
...
-To convert JSON string of size 89556 into JNode took 3.399 +/- 1.483 ms over 32 trials
-Load times (ms): 2, 3, 6, 5, 3, 1, 2, 3, 4, 2, 2, 5, 1, 1, 1, 2, 1, 1, 6, 2, 2, 3, 4, 4, 2, 3, 3, 1, 2, 5, 4, 5
+To convert JSON string of size 89556 into JNode took 2.762 +/- 1.319 ms over 32 trials
+Load times (ms): 5, 2, 3, 5, 1, 2, 5, 1, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 4, 3, 4, 1, 1, 2, 4
=========================
Performance tests for RemesPath (float arithmetic)
=========================
-Compiling query "@[@[:].a * @[:].t < @[:].e]" into took 2.598 +/- 15.789 microseconds over 40 trials
-To run pre-compiled query "@[@[:].a * @[:].t < @[:].e]" on JNode from JSON of size 89556 into took 0.069 +/- 0.272 ms over 40 trials
-Query times (ms): 0.067, 0.032, 0.024, 0.023, 0.023, 0.022, 0.023, 0.027, 0.024, 0.023, 0.023, 0.024, 0.023, 0.025, 1.769, 0.026, 0.024, 0.023, 0.023, 0.027, 0.023, 0.024, 0.042, 0.033, 0.032, 0.028, 0.023, 0.023, 0.023, 0.022, 0.022, 0.022, 0.022, 0.022, 0.022, 0.021, 0.022, 0.022, 0.022, 0.022
+Compiling query "@[@[:].a * @[:].t < @[:].e]" into took 2.618 +/- 15.946 microseconds over 40 trials
+To run pre-compiled query "@[@[:].a * @[:].t < @[:].e]" on JNode from JSON of size 89556 into took 0.074 +/- 0.316 ms over 40 trials
+Query times (ms): 0.076, 2.046, 0.025, 0.023, 0.023, 0.022, 0.022, 0.025, 0.022, 0.023, 0.022, 0.022, 0.022, 0.022, 0.021, 0.022, 0.021, 0.021, 0.021, 0.023, 0.021, 0.021, 0.021, 0.021, 0.021, 0.022, 0.022, 0.021, 0.021, 0.021, 0.021, 0.022, 0.021, 0.021, 0.021, 0.021, 0.021, 0.023, 0.028, 0.021
Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c"
...
=========================
Performance tests for RemesPath (string operations)
=========================
-Compiling query "@[@[:].z =~ `(?i)[a-z]{5}`]" into took 2.452 +/- 14.691 microseconds over 40 trials
-To run pre-compiled query "@[@[:].z =~ `(?i)[a-z]{5}`]" on JNode from JSON of size 89556 into took 0.119 +/- 0.091 ms over 40 trials
-Query times (ms): 0.15, 0.135, 0.103, 0.107, 0.103, 0.103, 0.103, 0.102, 0.102, 0.102, 0.102, 0.102, 0.684, 0.104, 0.103, 0.101, 0.102, 0.102, 0.102, 0.102, 0.103, 0.104, 0.102, 0.104, 0.102, 0.103, 0.102, 0.103, 0.102, 0.102, 0.102, 0.102, 0.103, 0.102, 0.103, 0.103, 0.102, 0.102, 0.104, 0.102
+Compiling query "@[@[:].z =~ `(?i)[a-z]{5}`]" into took 1.448 +/- 8.688 microseconds over 40 trials
+To run pre-compiled query "@[@[:].z =~ `(?i)[a-z]{5}`]" on JNode from JSON of size 89556 into took 0.058 +/- 0.015 ms over 40 trials
+Query times (ms): 0.113, 0.059, 0.111, 0.112, 0.068, 0.055, 0.056, 0.055, 0.053, 0.053, 0.054, 0.054, 0.052, 0.054, 0.053, 0.053, 0.054, 0.054, 0.053, 0.054, 0.056, 0.053, 0.053, 0.053, 0.053, 0.054, 0.053, 0.055, 0.053, 0.053, 0.052, 0.054, 0.053, 0.053, 0.052, 0.052, 0.053, 0.054, 0.052, 0.052
Preview of result: [{"A": "\n]o1VQ5t6g", "a": 4710024278, "b": 3268860721, "B": "g4Y7+ew^.v", "C": "NK nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" into took 9.315 +/- 56.379 microseconds over 40 trials
+ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" into took 5.035 +/- 30.147 microseconds over 40 trials
To run pre-compiled query "var qmask = @[:].q;
var nmax_q = max(@[qmask].n);
var nmax_notq = max(@[not qmask].n);
-ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" on JNode from JSON of size 89556 into took 0.026 +/- 0.035 ms over 40 trials
-Query times (ms): 0.102, 0.018, 0.017, 0.017, 0.016, 0.017, 0.053, 0.031, 0.016, 0.016, 0.042, 0.016, 0.016, 0.016, 0.016, 0.016, 0.227, 0.022, 0.017, 0.016, 0.016, 0.016, 0.016, 0.015, 0.016, 0.016, 0.016, 0.016, 0.017, 0.015, 0.016, 0.016, 0.016, 0.04, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016
+ifelse(nmax_q > nmax_notq, `when q=true, nmax = ` + str(nmax_q), `when q=false, nmax= ` + str(nmax_notq))" on JNode from JSON of size 89556 into took 0.018 +/- 0.008 ms over 40 trials
+Query times (ms): 0.067, 0.019, 0.017, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.024, 0.019, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.017, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.015, 0.016, 0.016, 0.016
Preview of result: "when q=false, nmax= 9830935647.0"
...
=========================
@@ -267,11 +267,11 @@ Performance tests for RemesPath (references to compile-time constant variables)
Compiling query "var X = X;
var onetwo = j`[1, 2]`;
-@[:]->at(@, X)->at(@, onetwo)" into took 2.912 +/- 17.564 microseconds over 40 trials
+@[:]->at(@, X)->at(@, onetwo)" into took 3.655 +/- 22.201 microseconds over 40 trials
To run pre-compiled query "var X = X;
var onetwo = j`[1, 2]`;
-@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.015 +/- 0.007 ms over 40 trials
-Query times (ms): 0.039, 0.026, 0.012, 0.013, 0.013, 0.013, 0.013, 0.012, 0.014, 0.013, 0.012, 0.012, 0.015, 0.028, 0.012, 0.012, 0.013, 0.04, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.013, 0.013, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.013, 0.012
+@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.026 +/- 0.075 ms over 40 trials
+Query times (ms): 0.042, 0.014, 0.023, 0.012, 0.013, 0.012, 0.493, 0.014, 0.012, 0.013, 0.012, 0.012, 0.012, 0.012, 0.021, 0.013, 0.012, 0.013, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.013, 0.012, 0.012, 0.012, 0.012, 0.013, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.013, 0.012
Preview of result: [[1695727848, 0.287562638736685], [2126430375, 0.00767794129708177], [5310550656, 0.380769772645687], [2519183283, 0.153176220930558], [6610062385, 0.662996225870666], [987168256, 0.924410189999928], [6615003609, 0.917112691225947], [4465232046, 0.684311931851536], [8654414565, 0.631485392105992], [
...
=========================
@@ -280,29 +280,29 @@ Performance tests for RemesPath (references to variables that are not compile-ti
Compiling query "var X = @->`X`;
var onetwo = @{1, 2};
-@[:]->at(@, X)->at(@, onetwo)" into took 4.392 +/- 26.502 microseconds over 40 trials
+@[:]->at(@, X)->at(@, onetwo)" into took 3.185 +/- 19.298 microseconds over 40 trials
To run pre-compiled query "var X = @->`X`;
var onetwo = @{1, 2};
-@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.033 +/- 0.009 ms over 40 trials
-Query times (ms): 0.087, 0.032, 0.032, 0.032, 0.032, 0.041, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032, 0.031, 0.032, 0.032
+@[:]->at(@, X)->at(@, onetwo)" on JNode from JSON of size 89556 into took 0.018 +/- 0.008 ms over 40 trials
+Query times (ms): 0.059, 0.016, 0.017, 0.028, 0.017, 0.022, 0.017, 0.016, 0.017, 0.028, 0.016, 0.016, 0.044, 0.016, 0.016, 0.016, 0.015, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.017, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016, 0.016
Preview of result: [[1695727848, 0.287562638736685], [2126430375, 0.00767794129708177], [5310550656, 0.380769772645687], [2519183283, 0.153176220930558], [6610062385, 0.662996225870666], [987168256, 0.924410189999928], [6615003609, 0.917112691225947], [4465232046, 0.684311931851536], [8654414565, 0.631485392105992], [
...
=========================
Performance tests for RemesPath (simple string mutations)
=========================
-Compiling query "@[:].z = s_sub(@, g, B)" into took 2.455 +/- 14.739 microseconds over 40 trials
-To run pre-compiled query "@[:].z = s_sub(@, g, B)" on JNode from JSON of size 89556 into took 0.102 +/- 0.479 ms over 40 trials
-Query times (ms): 0.036, 0.034, 0.024, 0.024, 0.014, 0.036, 0.029, 0.025, 0.024, 0.034, 0.022, 0.025, 0.032, 0.025, 0.027, 0.021, 0.018, 0.02, 0.02, 0.026, 0.028, 0.032, 0.026, 0.026, 0.025, 0.03, 0.028, 3.095, 0.044, 0.017, 0.022, 0.029, 0.023, 0.013, 0.021, 0.022, 0.029, 0.029, 0.021, 0.018
+Compiling query "@[:].z = s_sub(@, g, B)" into took 3.812 +/- 23.409 microseconds over 40 trials
+To run pre-compiled query "@[:].z = s_sub(@, g, B)" on JNode from JSON of size 89556 into took 0.015 +/- 0.005 ms over 40 trials
+Query times (ms): 0.027, 0.012, 0.011, 0.016, 0.01, 0.009, 0.009, 0.011, 0.011, 0.01, 0.022, 0.019, 0.015, 0.02, 0.015, 0.017, 0.014, 0.022, 0.011, 0.01, 0.011, 0.025, 0.01, 0.01, 0.012, 0.011, 0.034, 0.014, 0.012, 0.011, 0.011, 0.016, 0.014, 0.013, 0.016, 0.014, 0.014, 0.015, 0.014, 0.017
Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c"
...
=========================
Performance tests for RemesPath (simple number mutations)
=========================
-Compiling query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" into took 3.658 +/- 22.008 microseconds over 40 trials
-To run pre-compiled query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" on JNode from JSON of size 89556 into took 0.037 +/- 0.011 ms over 40 trials
-Query times (ms): 0.053, 0.046, 0.069, 0.051, 0.04, 0.028, 0.028, 0.027, 0.054, 0.04, 0.038, 0.038, 0.046, 0.036, 0.035, 0.039, 0.038, 0.044, 0.038, 0.037, 0.037, 0.048, 0.038, 0.05, 0.03, 0.065, 0.024, 0.019, 0.021, 0.021, 0.021, 0.03, 0.041, 0.033, 0.03, 0.027, 0.03, 0.027, 0.028, 0.028
+Compiling query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" into took 2.8 +/- 16.878 microseconds over 40 trials
+To run pre-compiled query "@[:].x = ifelse(@ < 0.5, @ + 3, @ - 3)" on JNode from JSON of size 89556 into took 0.033 +/- 0.01 ms over 40 trials
+Query times (ms): 0.044, 0.027, 0.024, 0.024, 0.042, 0.044, 0.036, 0.042, 0.032, 0.053, 0.04, 0.031, 0.038, 0.026, 0.024, 0.023, 0.035, 0.039, 0.04, 0.037, 0.038, 0.047, 0.052, 0.06, 0.037, 0.025, 0.022, 0.021, 0.022, 0.02, 0.021, 0.022, 0.022, 0.021, 0.02, 0.034, 0.031, 0.043, 0.025, 0.026
Preview of result: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c"
...
=========================
@@ -312,12 +312,12 @@ Performance tests for RemesPath (mutations with a for loop)
Compiling query "var xhalf = @[:].x < 0.5;
for lx = zip(@[:].l, xhalf);
lx[0] = ifelse(lx[1], foo, bar);
-end for;" into took 6.925 +/- 42.334 microseconds over 40 trials
+end for;" into took 6.665 +/- 40.582 microseconds over 40 trials
To run pre-compiled query "var xhalf = @[:].x < 0.5;
for lx = zip(@[:].l, xhalf);
lx[0] = ifelse(lx[1], foo, bar);
-end for;" on JNode from JSON of size 89556 into took 0.039 +/- 0.013 ms over 40 trials
-Query times (ms): 0.11, 0.062, 0.039, 0.041, 0.036, 0.044, 0.036, 0.036, 0.034, 0.038, 0.033, 0.034, 0.033, 0.035, 0.038, 0.034, 0.033, 0.032, 0.037, 0.034, 0.033, 0.032, 0.044, 0.035, 0.041, 0.037, 0.042, 0.038, 0.037, 0.036, 0.033, 0.039, 0.034, 0.033, 0.033, 0.039, 0.033, 0.033, 0.036, 0.04
+end for;" on JNode from JSON of size 89556 into took 0.052 +/- 0.021 ms over 40 trials
+Query times (ms): 0.104, 0.08, 0.068, 0.091, 0.059, 0.041, 0.085, 0.06, 0.049, 0.037, 0.038, 0.037, 0.037, 0.037, 0.037, 0.037, 0.036, 0.037, 0.036, 0.063, 0.038, 0.036, 0.037, 0.039, 0.039, 0.061, 0.058, 0.043, 0.038, 0.037, 0.051, 0.059, 0.062, 0.044, 0.11, 0.067, 0.099, 0.034, 0.035, 0.037
Preview of result: [["bar", false], ["bar", false], ["foo", true], ["foo", true], ["foo", true], ["foo", true], ["foo", true], ["bar", false], ["bar", false], ["bar", false], ["foo", true], ["foo", true], ["bar", false], ["bar", false], ["foo", true], ["bar", false], ["bar", false], ["bar", false], ["foo", true], ["ba
...
=========================
@@ -326,18 +326,18 @@ Testing performance of JSON compression and pretty-printing
Preview of json: [{"A": "Ky'c^g#~)0", "a": 1850111954, "b": 9318359041, "B": "Oyi:/ xxe2", "C": "sKCSa_^7Gg", "c": 7974777124, "d": 2670309238, "D": "0d_K)HmX!.", "E": ".uM*Z{0EJ_", "e": 6958410336, "f": 8050244728, "F": "1%SG_A!xB\t", "g": 3799657125, "G": "il1^k\\\nat*", "H": {"a": 6079042826, "b": 7292804611, "c"
...
-To compress JNode from JSON string of 89556 took 4.63 +/- 1.207 ms over 64 trials (minimal whitespace, sort_keys=TRUE)
-To compress JNode from JSON string of 89556 took 2.528 +/- 0.832 ms over 64 trials (minimal whitespace, sort_keys=FALSE)
-To Google-style pretty-print JNode from JSON string of 89556 took 5.126 +/- 1.181 ms over 64 trials (sort_keys=true, indent=4)
-To Whitesmith-style pretty-print JNode from JSON string of 89556 took 5.079 +/- 1.279 ms over 64 trials (sort_keys=true, indent=4)
-To PPrint-style pretty-print JNode from JSON string of 89556 took 8.083 +/- 1.833 ms over 64 trials (sort_keys=true, indent=4)
+To compress JNode from JSON string of 89556 took 4.056 +/- 0.303 ms over 64 trials (minimal whitespace, sort_keys=TRUE)
+To compress JNode from JSON string of 89556 took 2.097 +/- 0.181 ms over 64 trials (minimal whitespace, sort_keys=FALSE)
+To Google-style pretty-print JNode from JSON string of 89556 took 4.751 +/- 0.76 ms over 64 trials (sort_keys=true, indent=4)
+To Whitesmith-style pretty-print JNode from JSON string of 89556 took 4.315 +/- 0.414 ms over 64 trials (sort_keys=true, indent=4)
+To PPrint-style pretty-print JNode from JSON string of 89556 took 6.082 +/- 0.656 ms over 64 trials (sort_keys=true, indent=4)
=========================
Testing performance of JsonSchemaValidator and random JSON creation
=========================
-To create a random set of tweet JSON of size 168723 (15 tweets) based on the matching schema took 7.667 +/- 3.817 ms over 64 trials
-To compile the tweet schema to a validation function took 0.36 +/- 0.625 ms over 64 trials
-To validate tweet JSON of size 168723 (15 tweets) based on the compiled schema took 1.218 +/- 0.317 ms over 64 trials
+To create a random set of tweet JSON of size 159731 (15 tweets) based on the matching schema took 7.16 +/- 3.45 ms over 64 trials
+To compile the tweet schema to a validation function took 0.223 +/- 0.046 ms over 64 trials
+To validate tweet JSON of size 159731 (15 tweets) based on the compiled schema took 1.099 +/- 0.268 ms over 64 trials
=========================
Testing JSON grepper's API request tool
=========================