1

I use a managed package that gives me the ability to invoke Apex class, get result and handle it. My Static Resource (JS code) invokes Apex to fetch one or more records from the DB and return them back. I want to get all the fields of this record including null/empty values. So, because Database.Query(query)) does not include empty/null values, i modify a bit the sObject record to include them. However, when my Apex class returns the results to JS, my map does not include the null values!!! Is this logical? How can i overcome this?

/**
/**
 * ? 16/07/2021 @ggalaios
 * ! Generic Apex class called from OE Static Resources (Implements the CS Interface)
 * ! Consists of "Execute" method to return OE Data back to the static Resource that invoked the Class
 */

global class el_OE_DataHandler implements csoe.IRemoteAction {
    global Map<String,Object> execute(Map<String,Object> inputMap) {
        try {
        system.debug('called.' + inputMap);

        //Define the necessary variables that are expected to exist in the map
        String sObjectAPIName = (string) inputMap.get('sObjectAPIName'); //Mandatory
        system.debug('sObjectAPIName is: ' +sObjectAPIName);
        String recordId = (string) inputMap.get('recordId'); //Mandatory
        String fieldAPIName = (string) inputMap.get('fieldAPIName'); //Mandatory
        String orderByFieldAPIName = (string) inputMap.get('orderByFieldAPIName'); //Optional
            
        String queryString; //Query String to be used for SOQL Operation
        //get a Comma Separated List of fields
        String sObjectFields = el_GenericQuery.getSobjectFields(sObjectAPIName); 
        inputMap.clear(); //clear the input map

        //Handle QueryString depending the 'Order By' optional field
        if(String.isBlank(orderByFieldAPIName)) {
            //get all the fields of the given sObjectAPIName
            queryString = 'SELECT ' +el_GenericQuery.getSobjectFields(sObjectAPIName) +
            ' from ' +sObjectAPIName+ ' where ' +fieldAPIName+ ' = \'' + recordId + '\'';
        } else {
            //get all the fields of the given sObjectAPIName
            queryString = 'SELECT ' +el_GenericQuery.getSobjectFields(sObjectAPIName) +
            ' from ' +sObjectAPIName+ ' where ' +fieldAPIName+ ' = \'' + recordId + '\''
            + 'order by ' +fieldAPIName;
        }
        //Execute the query
        List<sObject> sObjectList = new List<sObject>();
        
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get(sObjectAPIName);
        Map<String, Schema.SObjectField> fieldMap = targetType.getDescribe().fields.getMap();

        //Iterate through each record returned
        for(sObject tmpSobject : Database.query(queryString)) {
            //for each field
            for(String field: fieldMap.keySet()) {
                //check if field's value is null. If yes, add it to the sObject record in order to be included
                if(tmpSobject.get(field) == null) {
                    tmpSobject.put(field, null);
                }
            }
            sObjectList.add(tmpSobject);
        }
        inputMap.put(recordId, sObjectList);
        system.debug('just before return...' +inputMap); //null values included in the map!
        return inputMap;
    } catch (Exception e) {
        system.debug('Exception occured: ' +e.getMessage() +'line is: ' +e.getLineNumber());
        return inputMap;
    }
}
}


Here is my static resource code that receives data from Apex. On console.log, null values are not included!!!

//function called when Apex returns Rate Card data
function updateRateCard(data) {
    
    console.log('upddata is: ' + JSON.stringify(data));
}

UPDATE 19/07/2021 Please find my updated code where i serialize the map in order to include null values. I replaced

inputMap.put(recordId, sObjectList);

with

inputMap.put(recordId, JSON.serialize(sObjectList));

1
  • Can you share the debug log from apex side of inputMap and also share console log of javascript end? Commented Jul 17, 2021 at 2:31

1 Answer 1

1

Null values aren't serialized, because they are null. If you absolutely need the values, you'll have to serialize the data into a JSON string, return it to the client, then parse it on the client side.

Here's a demonstration the problem and solution:

import { LightningElement, wire } from 'lwc';
import getMapValues from '@salesforce/apex/Q349771.getMapValues';
import getMapValuesAsJSON from '@salesforce/apex/Q349771.getMapValuesAsJSON';

export default class Q349771 extends LightningElement {
    resultOutput1 = '{loading}';
    resultOutput2 = '{loading}';
    @wire(getMapValues,{}) resultWireHandler1({data,error}) {
        if(data) {
            this.resultOutput1 = JSON.stringify(data);
        }
    }
    @wire(getMapValuesAsJSON,{}) resultWireHandler2({data,error}) {
        if(data) {
            this.resultOutput2 = JSON.stringify(JSON.parse(data));
        }
    }
}

<template>
    {resultOutput1}
    <hr />
    {resultOutput2}
</template>

Update:

You need to serialize the entire response, not just the records. This changes your code to:

global String execute(Map<String,Object> inputMap) {

...

inputMap.put(recordId, sObjectList);

...

return JSON.serialize(inputMap);
7
  • Hi sfdcfox and thanks for your response. By doing JSON.serialize() in my Apex before returning the map it includes the null values, as you suggested. However i have the following problem: When i do the JSON.serialize() in my Apex, in the debug log the format is exactly what i want. However, when returned to JS, instead of ' "" ', i have the symbol &amp;. Do you know why this happens and what i could do to handle this? Is it better to do a conversion in Apex or in JS? I tried to replace the ' &amp; ' with ' " ', but without success. Any suggestions? Commented Jul 18, 2021 at 10:51
  • @GiorgosGalaios That shouldn't happen. &amp; is for &, while " would have been encoded as &quot;. There may be something else going on. Can you share the updated code?
    – sfdcfox
    Commented Jul 18, 2021 at 15:25
  • I am sorry, i meant &quot;. This is what is shown in my serialized string. Not &amp; it was my typo. So is this a normal behavior? What is the best way to handle this? I also shared the update in my code (just one line is the change i did) Commented Jul 19, 2021 at 5:23
  • @GiorgosGalaios See my edit.
    – sfdcfox
    Commented Jul 19, 2021 at 5:48
  • thank you for the edits and all your advice. However, because my class implements and interface , it is needed to return a map of type <String, Object> as a response. So i cannot return a string to JS :( Commented Jul 19, 2021 at 5:53

You must log in to answer this question.

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