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
andjsonString
offieldName: fieldValue
, how can I generically deserialize this into a typed sObject?
Thank you for your suggestions
JSON.deserialize
. Regardless of whatevent.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.