Deserialize JSON to SObject

  • Following code is giving me common.apex.runtime.impl.ExecutionException

    String jsonText = '{"Data": {"attributes": {"type": "Contact"},"Id": "0036100000JUXKkAAP","Description": "","LastName": "Testing"}}';
    Map<String, Object> cObjMap = (Map<String, Object>) JSON.deserializeUntyped(jsonText); String cObjJson = JSON.serialize(cObjMap.get('Data')); SObject customObject = (SObject)JSON.deserialize(cObjJson, SObject.class);

    The problem is in fact that Map<String,Object> gets re-ordered during serialize/deserialize and "attributes" node is moved to last position.

    That causes deserialize to SObject to fail as it requires "attributes" to be in first position, just like in jsonText example.

    I know that defining separate class that would map all key/value pairs from JSON and deserializing to it would work, but I don't have exact structure as keys might vary.

    Do you have any idea how to accomplish this?

    Thank You!

    I'm pretty sure that the order won't get switched - maps are deterministic now. Can you confirm that "attributes" ends up at the end?

    Hmm, it does seem to mix it up, actually - going into the map. However, execute anon has no problem with this. Where are you seeing the error?

    What *type* is `cObjMap.get('Data')`? If you try and cast it to sObject you get the error: Invalid conversion from runtime type Map to SObject. So at best it is `Map`. Yes you can serialize it, but I don't think you can deserialize it as an sObject class instance. Nor can you deserialize a `Map` as Object isn't supported.

  • Ashwani

    Ashwani Correct answer

    5 years ago

    Well, this is how you can do it. Apex is made through Java!

    String jsonText = '{"Data": {"attributes": {"type": "Contact","url":"/services/data/v35.0/sobjects/Contact/0036100000JUXKkAAP"},"Id": "0036100000JUXKkAAP","Description": "","LastName": "Testing"}}';
    
    Map<String, Object> cObjMap = (Map<String, Object>) JSON.deserializeUntyped(jsonText);
    String cObjJson = JSON.serialize(cObjMap.get('Data'));
    // Why again :(
    Map<String, Object> cObjMapFurious = (Map<String, Object>) JSON.deserializeUntyped(cObjJson);
    String cObjJsonDrunk = JSON.serialize(cObjMapFurious);
    try
    {
        SObject customObject = (SObject)JSON.deserialize(cObjJsonDrunk, Sobject.class);
        System.debug(' Accomplished: '+customObject);
    }
    catch(Exception ex)
    {
        System.debug(' @@@@@ Don\'t visible '+ex.getMessage());
    }
    

    Thanks Ashwani, it works! Anyway, this looks more like a workaround for something that should be supported initially. I assume that your logic was to deserialize/serialize once again so the key-value pairs gets reverted back to starting state, with 'attributes' at first position.

    @NikolaJ. We are doing this for years! Thats the object serialization algorithm behavior used by Salesforce Apex :) They day it will be modified , no impact would occur in this code.

    Thank you for sharing the solution ~

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM