0

I created a generic LWC using a lightning-record-edit-form where user specifies sObjectName and fields to display as parameters and the edit form will display those.

<lightning-record-edit-form
           record-id={recordId}
           object-api-name={objectApiName}
           onsubmit={handleSubmit}>    
<template forEach={field} ...
<lighting-input-field ...>

When user clicks on submit, I would like to call an apex class and have that class deserialize the form into a specific object.

For example: on an app page, I configure my form to objectApiName ="Contact" and Fields = "FirstName, LastName"

I would like to imperatively call an apex class (pass whatever paramaters needed from JS) and within that class I would like to generically be able to deserialize my JS parameters into an sObject.

currently my event handler looks something like this:

handleSubmit(event){
    event.preventDefault();
    const fields = event.detail.fields;
    let strFields = JSON.stringify(fields);
    doBeforeSave{objectApiName: this.objectApiName, jsonFields: strFields}
    .then(()=>{...})
    .catch((error)=>{...}

If I know this is a Contact for example, in my Apex method I can do something like the following:

Contact c = (Contact)JSON.deserialize(strFields, Contact.class);

If my LWC was configured for an Account with Account fields, this would fail.

If I try to deserialize this the following way I get an error:

sObject myObj = (sObject)JSON.deserialize(strFields, sObject.class);

Nested object for polymorphic foreign key must have an attributes field before any other fields. So I would need an "Attribute": {...} appearing first, but I do not have that in my event.detail.fields object. See this question

I found a way that works by instantiating a new sObject, deserializing the jsonFields into a map<String, Object> and then putting these in the sObject:

sObject genericObj = sObjType.newSObject();
Schema.SObjectType t = Schema.getGlobalDescribe().get(objectApiName);
SObject sObj = t.newSObject();
Map<String, Object> fieldMap = (Map<String, Object>)JSON.deserializeUntyped(jsonFields);
for(String fieldName : fieldMap.keyset()){
    sObj.put(fieldName, fieldMap.get(fieldName));
}

but this does not seem optimal.

Any help on best way to:

  • given two strings: objectAPIName and jsonString of fieldName: fieldValue, how can I generically deserialize this into a typed sObject?

Thank you for your suggestions

6
  • Deserializing to sObject: please do a search on here, this question has been asked and answered. Here's one such Q&A: salesforce.stackexchange.com/questions/106309/… . It would be preferable if your second bullet is in its own question. Having multiple questions in one post makes it too broad and therefore less valuable to the community - see How to Ask for guidelines.
    – identigral
    Mar 18, 2021 at 16:01
  • Thanks for your feedback. I moved second bullet to its own question. I did thoroughly search for answers. I updated my question, while the link you refer to does address a similar topic, it does not answer my question. My effort and question is clearly defined and I believe that an answer to this question will be valuable for both myself and others in the community as well.
    – Z33dawg
    Mar 18, 2021 at 17:13
  • @identigral since you are an identity and access management pro maybe you can help bring insight to another unanswered question of mine --> salesforce.stackexchange.com/questions/336728/…
    – Z33dawg
    Mar 18, 2021 at 17:16
  • For typed deserialization, your JSON must meet the expectations of JSON.deserialize. Regardless of what event.detail produces, you have to build the right payload. This is tedious and not trivial but possible. What's the right payload? It depends on the object and the API version, so you have to go object by object. For an easier solution, untyped deserialization is the answer.
    – identigral
    Mar 18, 2021 at 18:07
  • 1
    For simple objects without nesting and relationships - yes, your example will work.
    – identigral
    Mar 18, 2021 at 18:40

0

You must log in to answer this question.