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);



(AggregateResult:{Name=1}, 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.


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]) {
  • Nice! I missed this one in Summer '16 release notes. :(
    – Mahmood
    Jan 8 '18 at 11:29
  • very Nice answer Keith c :) Jan 8 '18 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"
    – Basti
    Jan 8 '18 at 13:01
  • 3
    update: deserializeUntyped helped me out of the "object" issue.
    – Basti
    Jan 8 '18 at 13:18

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);

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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.