I'm trying to serialize, then deserialize an AccountHistory
record. However, whenever I include a read-only field, such as NewValue
, in the JSON, when I try to deserialize the record, I get this error:
System.UnexpectedException: Salesforce System Error: 158360809-105080 (2033965611) (2033965611)
Heres the code I'm working with:
AccountHistory history = [SELECT Id FROM AccountHistory WHERE Id = '017c000009RmtOFAAZ' LIMIT 1];
AccountHistory historyWithValue = [SELECT Id, NewValue FROM AccountHistory WHERE Id = '017c000009RmtOFAAZ' LIMIT 1];
String historyString = JSON.serialize(history);
SObject someObj = (sObject)JSON.deserialize(historyString, sObject.class); // Works
AccountHistory someHistory = (AccountHistory)JSON.deserialize(historyString, AccountHistory.class); // Works
String historyValueString = JSON.serialize(historyWithValue);
SObject anotherObj = (sObject)JSON.deserialize(historyValueString, sObject.class); // Fails
AccountHistory anotherHistory = (AccountHistory)JSON.deserialize(historyValueString, AccountHistory.class); // Fails
How can I deserialize JSON data which includes a record with read-only fields?
I know there's a method of using JSON to set the CreatedDate on records for test contexts, which is a read-only field, so there must be some solution. As this answer states:
This doesn't enforce the normal read-only field attributes that prevent you from setting a createdDate value.
However, this does not seem to be the case for other object fields. For example, this code works:
String someJson = '{"AccountHistory":{"CreatedDate":"2017-11-07T15:56:30.000+0000"}}';
AccountHistory history = (AccountHistory)JSON.deserialize(someJson, AccountHistory.class); // Works
But this code causes a Salesforce exception:
String someJson = '{"AccountHistory":{"NewValue":"SomeValue"}}';
AccountHistory history = (AccountHistory)JSON.deserialize(someJson, AccountHistory.class); // Fails
Trying to update either of these fields through a constructor causes this exception:
new AccountHistory(NewValue = DateTime.now(), CreatedDate = DateTime.now());
Field is not writeable: AccountHistory.NewValue
Field is not writeable: AccountHistory.CreatedDate
The error message for both fields is the same, however, the behavior of the fields vary when it comes to JSON
methods.
Trying to use Test.LoadData
also fails with the same exception type. This was tested using this .csv
file:
Field,OldValue,NewValue,AccountId
Name,SomeTest,AnotherTest,001c000001GWSaL
And this snippet in my @testSetup
method:
Test.loadData(Schema.SObjectType.AccountHistory.getsObjectType(), 'ActivityHistoryTestData');
System.UnexpectedException: Salesforce System Error: 797046050-85268 (-725019502) (-725019502)
The context behind this question involves creating test AccountHistory
records. Since the OldValue
and NewValue
fields are not writeable, and Field History tracking is disabled in test contexts, I'm left with few options for writing a test class. I've already refactored a number of functions to allow raw data to be passed to them, allowing me to test them without requiring any history records. However, I'd still like to be able to test some other methods to obtain full coverage.
My solution to this problem was to create json test data, and then deserialize the data into history records, or at least sObjects. However, I've run into some trouble with the conversion from a string into the object.
Test.loadData
?someSobjectHistory
records