function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
CarnVanBeckCarnVanBeck 

Bug - Unable to deserialize Time Class

I'm trying to parse a Time field from my lightning component to my apex controller by using JSON and deserializing it in apex into an existing Object.
But unfortunately I'm always getting the error
Cannot deserialize instance of time from VALUE_STRING value 10:30:00.000Z

I already tried different Time formats and with/without quotes "" in my JSON
  • 10:30
  • 10:30:00
  • 10:30:00.000
  • 10:30:00.000Z
  • T10:00:00.000Z
  • 2018-06-07T10:00:00.000Z
But nothing works.
My Org is on Spring 18 API Version 42
I have an SObject (Event__c) with a Time Field
The problem is reproducable in anonymous apex with following code
Event__c workingObject = new Event__c();
workingObject.Name = 'Lorem';
workingObject.Public_Start_Time__c = Time.newInstance(10,10,10,10);

String serializedObject = JSON.serialize(workingObject);
String mixedObject = '{"Public_Start_Time__c": "' + workingObject.Public_Start_Time__c + '", "name": "Ipsum"}';
String manualObject = '{"Public_Start_Time__c": "2018-06-07T10:00:00.000Z", "name": "Dolor"}';
try {
   Event__c banana = (Event__c)JSON.deserialize(serializedObject, Event__c.class);
}
catch(Exception ex) {
    System.debug(ex.getMessage());
}

try {
   Event__c banana = (Event__c)JSON.deserialize(mixedObject, Event__c.class);
}
catch(Exception ex) {
    System.debug(ex.getMessage());
}

try {
   Event__c banana = (Event__c)JSON.deserialize(manualObject, Event__c.class);
}
catch(Exception ex) {
    System.debug(ex.getMessage());
}
which results in the 3 following messages
Cannot deserialize instance of time from VALUE_STRING value 10:10:10.010Z or request may be missing a required field
Cannot deserialize instance of time from VALUE_STRING value 10:10:10.010Z or request may be missing a required field
Cannot deserialize instance of time from VALUE_STRING value 2018-06-07T10:00:00.000Z or request may be missing a required field

Everything I found so far was for dates or datetimes but not time only.

I made a Post at stackexchange:
https://salesforce.stackexchange.com/questions/220809/cannot-deserialize-instance-of-time-from-value-string-value

As a workaround I have build my own time parser, but it would be great if this could be fixed
NagendraNagendra (Salesforce Developers) 
Hi Carn,

Sorry for this issue you are encountering.

This is probably a bug, and I'd recommend contacting Salesforce Support (If you haven't already).

Heres a repo I wrote using a custom object (Test__c, with a single time field, Some_Time__c). It starts with the a demo using Time as the object, then runs the same code for Test__c. The raw Time object works, and has the same syntax as the JSON, but the JSON object fails with the same message.
Time t = DateTime.now().Time(); 
String s = JSON.serialize(t); 

System.debug(s); // "13:50:40.848Z"

Time t2 = (Time)JSON.deserialize(s, Time.class);

System.debug(t2); // 13:50:40.848Z

Test__c test = new Test__c(
    Some_Time__c = DateTime.now().Time()
);

String testString = JSON.serialize(test);

System.debug(testString);
// {"attributes":{"type":"Test__c"},"Some_Time__c":"13:50:40.850Z"}
// "13:50:40.850Z"

Test__c result = (Test__c)JSON.deserialize(testString, Test__c.class);

Some additional notes from my test runs:
  • Using Map<String, Object> record = (Map<String, Object>)JSON.deserializeUntyped(testString); returns a valid Time string in the map.
  • Trying to access this with System.debug((Time)record.get('Some_Time__c')); fails with a:
System.TypeException: Invalid conversion from runtime type String to Time
  • Since theres no Time.Parse method, I cant figure out a good way to get the string value back into a Time object

You'll probably need a custom parse method, for both the Time string & the JSON. I've written up a sample below. Keep in mind that this is a basic example and an actual parser would likely need better code to put other field values.

The custom parser does output a proper object however! You can use describes instead of field names (likely with a map of field names & types) to determine what fields are time fields & to use a special case for those fields.
Test__c test = new Test__c(
    Some_Time__c = DateTime.now().Time()
);

String testString = JSON.serialize(test);

JSONParser parser = JSON.createParser(testString);

Test__c testCustom = new Test__c(); 

while (parser.nextToken() != null) {
    if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {

        System.debug(parser.getText());
        if (parser.getText() == 'Some_Time__c') {
            String label = parser.getText(); 

            parser.nextValue();

            testCustom.put(label, CustomTimeParser(parser.getText()));
        } else {
            String label = parser.getText(); 

            parser.nextValue();

            testCustom.put(label, parser.getText()); 
        }
    }
}

System.debug(testCustom);
// Test__c:{Some_Time__c=14:26:41.276Z}

public static Time CustomTimeParser(String s) {
    // 14:26:41.276Z
    List<String> values = s.replace('Z', '').split(':'); 

    // (14, 26, 41.276)         
    String hours = values[0]; 
    String minutes = values[1];

    // 41.276 -> (41, 276) 
    String seconds = values[2].split('\\.')[0];
    String milliseconds = values[2].split('\\.')[1];

    return Time.newInstance(Integer.valueOf(hours), Integer.valueOf(minutes), Integer.valueOf(seconds), Integer.valueOf(milliseconds));
}
Hope this helps.

Kindly mark this as solved if the reply was helpful.

Thanks,
Nagendra