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

Strange error with JSON serialize/deserialize: "Cannot deserialize instance of <unknown> from FIELD_NAME value totalSize or request may be missing a required field"

I'm seeing some weird behavior while trying to deserialize json containing some Accounts with child objects.  Example code:
String accountsJson = 
'[' +
'    {' +
'        "attributes": {' +
'            "type": "Account",' +
'            "url": "/services/data/v32.0/sobjects/Account/a0YG0000005Jn5uMAC"' +
'        },' +
'        "Name": "Fred",' +
'        "Id": "a0YG0000005Jn5uMAC",' +
'        "abc__r": {' +
'            "totalSize": 1,' +
'            "done": true,' +
'            "records": [' +
'                {' +
'                    "attributes": {' +
'                        "type": "abc__c ",' +
'                        "url": "/services/data/v32.0/sobjects/abc__c /a0ZG0000006JGPAMA4"' +
'                    },' +
'                    "Name": "Bob",' +
'                    "Id": "a0ZG0000006JGPAMA4",' +
'                    "Account__c": "a0YG0000005Jn5uMAC"' +
'                }' +
'            ]' +
'        }' +
    '}' +

List<Account> accts = (List<Account>) JSON.deserialize(accountsJson, List<Account>.class);

The json shows a list of Accounts with only 1 Account, along with with a custom child object, abc__c (master-detail relationship).  Now, the above code is working fine for the abc__c object, however I have another custom object in my org with the exact same relationship to Account, lets call it xyz__c.  If I change the above json to use xyz__c child objects (via s/abc/xyz/g), then I get the following error during the deserialization:

"System.JSONException: Cannot deserialize instance of <unknown> from FIELD_NAME value totalSize or request may be missing a required field"

Incidentally - I have also reproduced this problem by inserting and querying for records and then serializing those results and then immediately deserializing the results, like so:
Savepoint sp = Database.setSavepoint();
Account a = new Account(Name = 'test acct');
insert a;
abc__c abc = new abc__c (
	Account__c = a.Id
insert abc;

List<Account> accts = [select Id,
                    (select Id
                        from abc__r)
                from Account where Id = :a.Id];
String acctStr = JSON.serialize(accts[0]);
JSON.deserialize(acctStr, Account.class);
The above code works fine for abc__c, but not xyz__c.

I was writing some unit tests and I needed to mock some query results for a list of Accounts with child data as well.  Since the relationship fields aren't writable (like Account.Opportunities, for example), the way to do that is through JSON serialization/desaerialization.  I've done this in the past, and I went about it the same way I have before and started seeing this error.  It's only this particular custom object where I'm getting this problem.  I went ahead and switched over to the ApexMocks method for doing this as well (fflib_ApexMocksUtils.makeRelationship) and I ran into the same error there.
Incidentally, if I'm reproducing starting with a raw json string (instead of serializing a query result), then the error message complains about the very first field it encounters within the relationship object definition - either "totalSize", "done", or "records" - whichever is defined first in the object.
For posterity, this is now a known issue:

The problem arises when there are two objects each with a lookup field to the other and you query them both with a subquery.  Deserializing the JSON representation of that data fails.
For posteriry, this is now a known issue:

Basically the problem arises when you have two objects that each have a lookup to the other and you query both (using a subquery).  Deserializing the JSON representation of that data results in the error.