10

Is it possible to deserialize AggregateResults? If not, why?

When I try it the regular way, all my aggregate results are empty:

List<AggregateResult> arList = [SELECT Name FROM Account GROUP BY Name LIMIT 2];

String arJson = JSON.serialize(arList);

List<AggregateResult> result = (List<AggregateResult>) 
                                    JSON.deserialize(arJson, List<AggregateResult>.class);

System.debug(arList);
System.debug(arJson);
System.debug(result);

Result:

(AggregateResult:{Name=1}, AggregateResult:{Name=AnAccount})

[{"attributes":{"type":"AggregateResult"},"Name":"1"},{"attributes":{"type":"AggregateResult"},"Name":"AnAccount"}]

(AggregateResult:{}, AggregateResult:{})

I'm trying to avoid additional wrappers and I'm interested in the reason why it doesn't work as expected.

0

2 Answers 2

12

I would have expected the serialization to work...

A workaround is to use Map<String, Object> instead (as an AggregateResult is usually consumed much like a Map) which will serialize and can be created reasonable easily:

List<Map<String, Object>> results = new List<Map<String, Object>>();
for (AggregateResult ar : [SELECT Name n FROM Account GROUP BY Name LIMIT 2]) {
    results.add(ar.getPopulatedFieldsAsMap());
}
4
  • Nice! I missed this one in Summer '16 release notes. :(
    – Mahmood
    Commented Jan 8, 2018 at 11:29
  • very Nice answer Keith c :)
    – Annappa PH
    Commented Jan 8, 2018 at 11:35
  • Really love this idea, but it won't work, since I'm getting this error message during deserialisation: "System.JSONException: Apex Type unsupported in JSON: Object"
    – itsmebasti
    Commented Jan 8, 2018 at 13:01
  • 3
    update: deserializeUntyped helped me out of the "object" issue.
    – itsmebasti
    Commented Jan 8, 2018 at 13:18
4

I don't think serialization on AggregateResult works because AggregateResult is not a "real" sObject, so it doesn't have any of its own fields. JSON.deserialize ignores fields which do not map to the serialized type, but if we try with JSON.deserializeStrict, we see a different result:

List<AggregateResult> results = [select Name from Account Group by Name limit 2];
String js = JSON.serialize(results);
Object deserial = JSON.deserializeStrict(js, List<AggregateResult>.class);

This will throw "No such column 'Name' on sobject of type AggregateResult"

On the other hand, if the aggregated column is ID, this will work because AggregateResult objects have ID as a concrete field (probably inherited from sObject):

List<AggregateResult> results = [select ID from Lead Group by ID limit 2];
String js = JSON.serialize(results);
Object deserial = JSON.deserializeStrict(js, List<AggregateResult>.class);
System.debug(deserial);

This will correctly deserialize into a list of AggregateResult objects with the "ID" field populated.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .