[SalesForce] JSON serialize SObject including fields with null values

I've currently got a use case where I would like to JSON serialize an SObject, but include fields with null (blank) values.

According to the documentation (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_Json.htm), using JSON.serialize(objectToSerialize, suppressApexObjectNulls) should give me the option to suppress null values or not. But it doesn't seem to be the case for SObjects. Take this example:

Account account = [SELECT Id, Name, AccountNumber FROM Account WHERE Id = '001b000000Irj49'];
system.debug(JSON.serialize(account, false));

Returns:

{
  "attributes": {
    "type": "Account",
    "url": "\/services\/data\/v42.0\/sobjects\/Account\/001b000000Irj49AAB"
  },
  "Id": "001b000000Irj49AAB",
  "Name": "Ben"
}

Where the AccountNumber field for my test record is null, but I would actually like it to be in my JSON.

However, if I run:

Account account = new Account(Name = 'Ben', AccountNumber = null);
system.debug(JSON.serialize(account, false));

I get:

{
  "attributes": {
    "type": "Account"
  },
  "Name": "Ben",
  "AccountNumber": null
}

So it seems like I would only get a null value if I explicitly assign null to the SObject.

Obviously I can iterate over each field in the object and build the JSON structure that way, but I would prefer to keep it a simple one line. My other test case is using a wrapper class, which seems to work when toggling suppressApexObjectNulls.

Best Answer

As per the Apex Dev Guide, Starting with API version 28.0, null fields aren’t serialized and aren’t included in the JSON string, unlike in earlier versions. This change doesn’t affect deserializing JSON strings with JSON methods, such as deserialize(jsonString, apexType). This change is noticeable when you inspect the JSON string.

The sample code below explains the difference between the results obtained for content queried via SOQL using API v27.0 and earlier versus its later versions.

String jsonString = JSON.serialize(
                 [SELECT Id, Name, Website FROM Account WHERE Website = null LIMIT 1]);
System.debug(jsonString);

// In v27.0 and earlier, the string includes the null field and looks like the following.
// {"attributes":{...},"Id":"001D000000Jsm0WIAR","Name":"Acme","Website":null}

// In v28.0 and later, the string doesn’t include the null field and looks like 
//  the following.
// {"attributes":{...},"Name":"Acme","Id":"001D000000Jsm0WIAR"}}

This implies, you will need to write a custom wrapper based or getGlobalDescribe() based logic to include null values within your serialized Json.

Refer the following link https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_json_json.htm to understand this.