21

I've been working quite a bit with @RemoteAction methods and have noticed there seem to be a few inconsistencies between what's allowed in the apex JSON.(de)serialize methods and what the automatic serialization/deserialization performed by @RemoteAction methods does.

Is there any authoritative list of what the different capabilities and limitations are of each? If not, what differences have you found?

As an example JSON.deserialize will not allow a type that contains a member of type object, while @RemoteAction parameters will deserialize any type of primitive that JSON supports into the object property.

0

2 Answers 2

19

I've experienced a couple gotchas and differences:

  1. DateTimes de/serialize as quoted strings:

    String christmasLunch = '2013-12-25T12:30:59.500Z'; //looks reasonable, runs ok too
    Json.deserialize(christmas, DateTime.class); //2013-01-01 00:00:00 - no month! no day!
    
    String independenceDay = '"2014-07-04T09:00:00.00Z"'; //carefully note double quotes
    Json.deserialize(independenceDay, DateTime.class); //2014-07-04 09:00:00 - better
    
  2. The serializer used by REST services can return nested result sets, for example:

    //SELECT Id, Name (SELECT Id, Name FROM Contacts) FROM Account
    [{
        "Id": "001000000000000AAA",
        "Name": "Test Account",
        "Contacts": [{
            "Id: "003000000000000AAA"
            "Name": "Test Contact"
        }
    }]
    

    For a time, the @RemoteAction serializer did not. (Until v28.0 - this is now documented).

  3. Whacky types may be serializable, but rightly throw a System.JSONException on deserialize:

    • Type Type unsupported in JSON: common.apex.runtime.bytecode.BytecodeSObjectType

    • DescribeSObjectResult No suitable constructor found for type

  4. @RemoteAction methods can serialize, but not deserialize ENUM values

    //apex:
    public enum SEASON {WINTER, SPRING, SUMMER, AUTUMN}
    @RemoteAction static public void parseSeason(SEASON which) {}
    
    //javascript:
    RemoteController.parseSeason('WINTER', function() {})
    //Exception: Unable to convert parameter to Apex type: expected SEASON, got String
    
  5. SObject DateTime must be transmitted Long unix timestamp format:

    //apex:
    @RemoteAction static public void parseUser(User me) {}
    
    //javascript:
    RemoteController.parseUser({CreatedDate: 1234567890000}, function() {})
    //this works fine
    
  6. but Apex DateTime must be transmitted in a different UTC String format:

    //apex
    @RemoteAction static public void parseDateTime(DateTime now) {}
    
    //javascript:
    RemoteController.parseDateTime(1234567890000, function() {})
    //Exception: Unable to convert date '1234567890000' to Apex type Datetime.
    
  7. watch out for crazy getter/setter action. Like SoapClient class mappings in PHP, they're not called!

2
5

In addition to JSON.deserialize not supporting types with object properties I've found:

  • Returning from a @RemoteAction doesn't run getters, JSON.serialize does
  • JSON.deserialize and @RemoteAction deserialization both run setters (as you'd expect)
  • JSON.deserialize will not handle deserializing into List<Object>, @RemoteAction deserialization will deserialize primitives properly into List<Object> but complex types will deserialize as nulls.

You must log in to answer this question.

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