How to Dynamically get any Value from a Custom Apex Object

Author: Bruce Tollefson Published: February 8, 2023; Modified: February 16, 2023
code

If you have worked with SObjects log enough you may have very well used the get() method. This method allow the ability to get any value using the SObjects value key. This is handy when trying to dynamically get a value. As an example I have an sObject list with Leads, Accounts, and Opportunities. They all have a field with the api of: Custom_Field__c and I need to get the value. I can loop through the list and get that value such as:

for(sObject sobj :sObjectList){ system.debug(sobj.get('Custom_Field__c')); }

I am sure you can think of a few other instances where this is useful. However what if you need to do something similar with a custom apex class object you create? How would you do the same? There are several different variations that you can use in order to achieve this goal.

JSON Deserializer

The first method would be to use the JSON.serialize() method and then JSON.deserializeUntyped() method. This method returns a Map<String, Object> and can be used to dynamically get any value from the the map and return the value as an object. ex:

public class CustomApexObject { public String variableA; public String variableB; public CustomApexObject(){ this.variableA= 'variableA value'; this.variableB = 'variableB value'; } }
CustomApexObject customObject = new CustomApexObject(); Map objectMap = (Map)JSON.deserializeUntyped(JSON.serialize(customObject)); system.debug(objectMap.get('variableA')); //'variableA value' system.debug(objectMap.get('variableB')); //'variableB value'

An alternative would be to put the deserialization in the class to hide it and not have worry about putting the code all over.

Hiding the Deserialization

Here is an example:

public class CustomApexObject { public String variableA; public String variableB; public CustomApexObject(){ this.variableA= 'variableA value'; this.variableB = 'variableB value'; } public Object get(String fieldName){ Map objectMap = (Map)JSON.deserializeUntyped(JSON.serialize(this)); return objectMap.get(fieldName); } }

If you wanted to optimize it a little bit so you don’t serialize and deserialize all the time you could change it to:

public class CustomApexObject { public String variableA; public String variableB; public CustomApexObject(){ this.variableA= 'variableA value'; this.variableB = 'variableB value'; } private Map objectMap; public Object get(String fieldName){ if(objectMap == null){ objectMap = (Map)JSON.deserializeUntyped(JSON.serialize(this)); } return objectMap.get(fieldName); } }

The you can get the values as such:

CustomApexObject customObject = new CustomApexObject(); system.debug(customObject .get('variableA')); //'variableA value' system.debug(customObject .get('variableB')); //'variableB value'

What if the values weren’t going to be originally there? The above methods require the values to already be set. One way to do that would be to use a setter for each of the variables.

Custom Object Setter

Here is an example of using a setter that updates a private map that can be called in the same fashion as the get method above:

public class CustomApexObject { public String variableA{get; set{ this.variableA = value; this.objectMap.put('variableA', value); } }; public String variableB{get; set{ this.variableB = value; this.objectMap.put('variableB', value); } }; private Map objectMap; public Object get(String fieldName){ return objectMap.get(fieldName); } }

Here is an example of how it would be used:

CustomApexObject customObject = new CustomApexObject(); customObject .variableA = 'variableA value'; customObject .variableB = 'variableB value'; system.debug(customObject .get('variableA')); //'variableA value' system.debug(customObject .get('variableB')); //'variableB value'

Then this can all be combined.

Combining Functionality

If you needed flexibility to do both you can create the following:

public class CustomApexObject { public String variableA{get; set{ this.variableA = value; if(this.objectMap == null){ this.objectMap.put('variableA', value); } } }; public String variableB{get; set{ this.variableB= value; if(this.objectMap == null){ this.objectMap.put('variableB', value); } } }; private Map objectMap; public Object get(String fieldName){ if(this.objectMap == null){ this.objectMap = (Map)JSON.deserializeUntyped(JSON.serialize(this)); } return objectMap.get(fieldName); } }

Note

Quick note if you are using private access modifiers when you deserialize the object if that private value is set you will be able to access that variable outside of the class.

Leave a Reply

Your email address will not be published. Required fields are marked *