19

Is it possible to access Apex class properties dynamically? While we can create Object's, and assign any other class to an Object, I'm not sure how I can access the properties of these Object's. Can anyone provide some documentation or references to code which would allow me to do this?

Example:

public class XYZ {
   public string s1 { get; set; }
   public string s2 { get; set; }
}

XYZ testXyzObj = new XYZ();
Object obj = testXyzObj;

// Method does not exist or incorrect signature: [Object].get(String)
String s1 = obj.get('s1'); 
| improve this question | | | | |
  • Unfortunately, that is not possible in apex at this moment of time. Only thing, that you can do -- create custom interface(or abstract class, and extend your own from that) with method getCustom(String param_name). Those method should serialize current class instance into string, deserialize as untyped, and return value by param_name(probably, with extra validations) – kurunve Aug 8 '16 at 9:18
  • Or another approach is to add a Map<String,Object> and have the getters and setters store the values in there keyed by name. – Keith C Aug 8 '16 at 9:46
  • Thank you Kurunve for your response. I think we will have to fix the number of the properties in the class right? But in our case, we will never know the number of the properties, its dynamic. Do you think this support our requirement? Thanks – Shrivaths Kulkarni Aug 8 '16 at 10:47
  • Thank you Keith, Sorry I did not get completely your approach. Could you please explain little more. Thanks – Shrivaths Kulkarni Aug 8 '16 at 10:47
  • @ShrivathsKulkarni check my example code in answer below. Not sure why do you need to fix amount of properties, my method would work with any amount of properties – kurunve Aug 8 '16 at 10:57
29

Unfortunately, that feature is not supported via default Apex. But there is something, which is possible to do in this case -- create custom get method, and extend your classes from your base custom object (CoreObject in example below):

public abstract class CoreObject{
    public Object getX(String param_name){
            String json_instance = Json.serialize(this);
            Map<String, Object> untyped_instance;
            untyped_instance= (Map<String, Object>)JSON.deserializeUntyped(json_instance);
            return untyped_instance.get(param_name);
    }
}

So, in that case, for every class, where you need generic get method, you can define your class as ancestor of this class, like

public class MyMegaClass extends CoreObject {
    public String var1;
    public Integer var2;
}

And use it like:

MyMegaClass c = new MyMegaClass();
c.var1 = 'test1';
c.var2 = 12;

String generic_value1 = (String)c.getX('var1');
System.debug(c.getX('var2'));

Warning: In case if class has self reference, that may cause issue with JSON loop serialization/deserialization.

| improve this answer | | | | |
  • 2
    Just fyi get is not a reserved word. – Adrian Larson Aug 8 '16 at 14:31
  • 1
    @AdrianLarson, thanks for note, but in this case I want to distinguish between standard get method and custom one, just for better understanding of the approach (and I was not sure of course ) – kurunve Aug 8 '16 at 17:56
13

Using an internal map for this purpose has the advantage that get/set access performance doesn't degrade as more fields are added:

public class XYZ {

    private Map<String, Object> m = new Map<String, Object>();

    // "Dynamic" getter
    public Object get(String key) {
        return m.get(key);
    }

    // "Dynamic" setter
    public void put(String key, Object value) {
        m.put(key, value);
    }

    // Static access to the same data
    public String s1 {
        get { return (String) get('s1'); }
        set { put('s1', value); }
    }

    // Static access to the same data
    public Integer i2 {
        get { return (Integer) get('i2'); }
        set { put('i2', value); }
    }
}

Best to write a code generator if you want to do very much of this to avoid typo mistakes.

| improve this answer | | | | |
1

Tried this today doing a .get on an sObject containing a variable string and Apex returned the value fine- not sure if this is a recent update but it now seems to work natively.

| improve this answer | | | | |
  • 3
    SObject has always supported this, but not the generic Object class. – Charles T Sep 21 '18 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.