The [List.GroupBy:] Macro now supports all JSON property types in Normal Mode
We’re excited to announce a significant enhancement to the [List.GroupBy:] macro in ReportMagic. Previously, Normal Mode could only group by string properties - meaning integer fields like severity, boolean fields like cleared, and null values would cause errors.
The Problem
When working with data from APIs like LogicMonitor, properties come in various JSON types. An alert object might look like this:
{
"id": "LMS123456",
"severity": 2,
"cleared": false,
"acked": false,
"sdted": false,
"tenant": "PDL",
"type": 1,
"resourceTemplateId": 111613363,
"resourceTemplateName": "SSL Certificates-",
"monitorObjectName": "web-server-01",
"suppressedDescending": null
}
Notice how severity is an integer, cleared is a boolean, and suppressedDescending is null. The old implementation would only works for strings. Grouping by any non-string property would fail.
What’s New
Normal Mode now fully supports grouping by properties of any primitive JSON type:
Strings - e.g. tenant,monitorObjectName(worked before, still works)
Integers - e.g. severity,type,resourceTemplateId
Booleans - e.g. cleared,acked,sdted
Null values - correctly distinguished from empty strings
Floats, GUIDs, Dates, TimeSpans, URIs - all supported
Type Preservation in Output
One of the key benefits is that output JSON retains the original property types. Previously, even if grouping had worked, all grouped values would have been converted to strings. Now:
Grouping by integer severity produces:
[
{ "severity": 2, "AlertCount": 270 },
{ "severity": 3, "AlertCount": 28 },
{ "severity": 4, "AlertCount": 2 }
]
Note that severity remains an integer (2, not "2") in the output. This matters when the output feeds into charts, tables, or further macro processing.
Grouping by boolean cleared produces:
[
{ "cleared": true, "AlertCount": 299 },
{ "cleared": false, "AlertCount": 1 }
]
Again, cleared is a proper boolean (true, not "true").
Multi-Property Grouping with Mixed Types
You can now freely combine properties of different types in a single groupBy. For example, grouping by tenant (string) + acked (boolean) + severity (integer):
[
{ "tenant": "PDL", "acked": false, "severity": 2, "AlertCount": 270 },
{ "tenant": "PDL", "acked": false, "severity": 3, "AlertCount": 28 },
{ "tenant": "PDL", "acked": false, "severity": 4, "AlertCount": 2 }
]
Three different types, all preserved correctly in the output.
Null vs Empty String
A subtle but important improvement: null values are now properly distinguished from empty strings. If you group by a property like suppressedDescending that can be either null or a string value, you’ll get separate groups:
[
{ "suppressedDescending": null, "Count": 295 },
{ "suppressedDescending": "some-value", "Count": 5 }
]
Previously this distinction was lost.
Practical Examples
Here are some real-world examples using LogicMonitor alert data. All examples assume you first fetch and parse alerts:
[LogicMonitor.AlertList: deviceGroup=PDL - Panoramic Data/Datacenter, properties=AllAsJson, take=300, =>AlertArray]
[Json.List: value=`{=AlertArray}`, jsonPath="$.[*]", =>Alerts]
Group by integer severity with Count:
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=severity,
aggregations=id^Count^AlertCount,
mode=normal,
=>AlertsBySeverity
]
Group by boolean cleared with Min/Max severity:
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=cleared,
aggregations=severity^Min^MinSeverity;severity^Max^MaxSeverity;id^Count^AlertCount,
mode=normal,
=>SeverityRangeByCleared
]
Mean severity by alert type:
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=type,
aggregations=severity^Mean^AvgSeverity;severity^Sum^TotalSeverity;id^Count^Count,
mode=normal,
=>AvgSeverityByType
]
Comprehensive template analysis:
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=resourceTemplateId,
aggregations=resourceTemplateName^First^TemplateName;severity^Min^MinSev;severity^Max^MaxSev;severity^Mean^AvgSev;id^Count^AlertCount,
mode=normal,
=>TemplateAnalysis
]
This produces a rich dataset showing, for each template, the template name, severity range, average severity, and alert count — all with the resourceTemplateId preserved as a proper integer.
Alert status breakdown with boolean grouping:
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=acked;cleared,
aggregations=severity^Sum^TotalSeverity;severity^Mean^AvgSeverity;id^Count^Count,
mode=normal,
=>SeverityStatsByStatus
]
Three-property grouping (string + boolean + integer):
[List.GroupBy:
values=`{=Alerts}`,
groupByObjectProperties=tenant;acked;severity,
aggregations=id^Count^AlertCount;alertValue^First^SampleAlert,
mode=normal,
=>DetailedAlertBreakdown
]
All Available Aggregation Types
As a reminder, all of these aggregation types work with the enhanced grouping:
| Aggregation | Description |
|---|---|
| Count | Number of non-null items in the group |
| Sum | Sum of numeric values |
| Min | Minimum numeric value |
| Max | Maximum numeric value |
| Mean | Average of numeric values |
| First | First value encountered in the group |
| Last | Last value encountered in the group |
Summary
If you’ve been working around the string-only limitation by converting properties to strings before grouping, you can now remove those workarounds. Just point groupByObjectProperties at any property: integer, boolean, null, or string - and it will work correctly with full type preservation in the output.
This enhancement is available in version 4.1.
Have questions or feedback? Reply below or raise an issue via the feedback form in ReportMagic.