4

I have an @AuraEnabled API where the serialization of Map<String, Object> works so was a bit surprised when the serialization of List<Map<String, Object>> didn't generating a gack on the first line of code that the deserialized data was referenced.

My client-side action is sending this JSON:

[  
    {  
        "Contact:cve__CommunicationPreference__c":"Email",
        "Contact:FirstName":"J",
        "Contact:LastName":"D",
        "Contact:Phone":"123"
    }
]

and the method signature is:

@AuraEnabled
public static List<Map<String, Object>> upsertParties(
        Id parentId,
        String partyType,
        String[] qualifiedFields,
        List<Map<String, Object>> values
        ) {
    ...
    // Gack on the first reference to values
    for (Map<String, Object> row : values) {
        ...
    }
    ...
}

I'm aware that using a JSON string instead is a work-around. But does anyone have these more complex combinations of collections working or have insight into what the problem is?

(The Apex JSON class handles these sorts of structures well; seems as if there is something substantially different about the serialization used for @AuraEnabled.)

3

I am using something similar to your Map<String, Object> but inside one of my Object values is actually a List<CustomWrapper>. I do round-trips with my Map<String, Object> engineCache.

The following works for me to re-initialize(?) the data server-side when it comes in through a Lightning JS Controller.

  private static List<IPE_EngineDataDisplayWrapper> extractWrapperDataFromEngineCache(Map<String, Object> engineCacheMap) {
    return (List<IPE_EngineDataDisplayWrapper>) JSON.deserialize(
      JSON.serialize(
        engineCacheMap.get(IPE_Constants.ENGINE_CACHE_WRAPPER_KEY)
      ), 
      List<IPE_EngineDataDisplayWrapper>.class
    );
  }

I imagine you might need to do something similar to explicitly cast is back to your List?

Something like:

for (Map<String, Object> row : (List<Map<String, Object>>) values) {
    // stuff
}
| improve this answer | |
  • Think this is a somewhat different situation. In my case I suspect the problem is the 2 levels of collection (List of Map). – Keith C May 17 '18 at 20:47
  • I did some further investigation of your data structure and I can't even seem to get Apex to recognize your List has any data. It correctly debugs size but it looks like the Aura Framework nulls out each item in your (parent) array. – tsalb May 17 '18 at 21:49
  • Thanks. All I got was a gack, but either way it's broken. – Keith C May 17 '18 at 22:01
2

I got some insight when applying the standard work-around of passing a JSON string from the JavaScript.

This code:

@AuraEnabled
public static List<Map<String, Object>> upsertParties(
        Id parentId,
        String partyType,
        String[] qualifiedFields,
        String listOfMapsJson
        ) {
    List<Map<String, Object>> values = (List<Map<String, Object>>) JSON.deserializeUntyped(listOfMapsJson);
    ...
}

generates the runtime error:

Invalid conversion from runtime type List<ANY> to List<Map<String,ANY>>

Presumably the @AuraEnabled deserialization is running into the same problem but is failing to generate a helpful error message.

To get the correct types code like this is needed:

    List<Map<String, Object>> values = new List<Map<String, Object>>();
    for (Object o : (List<Object>) JSON.deserializeUntyped(listOfMapsJson)) {
        values.add((Map<String, Object>) o);
    }
| improve this answer | |
  • Glad you figured it out, that's some nasty casting you're forced to do to get it back to a readable state sadly! – tsalb May 18 '18 at 16:39

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.