24

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'); 
5
  • 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
    Commented Aug 8, 2016 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
    Commented Aug 8, 2016 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 Commented Aug 8, 2016 at 10:47
  • Thank you Keith, Sorry I did not get completely your approach. Could you please explain little more. Thanks Commented Aug 8, 2016 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
    Commented Aug 8, 2016 at 10:57

2 Answers 2

37

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.

9
  • 5
    Just fyi get is not a reserved word.
    – Adrian Larson
    Commented Aug 8, 2016 at 14:31
  • 3
    @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
    Commented Aug 8, 2016 at 17:56
  • Is there are similar snippet for a SET method? Commented Oct 15, 2022 at 6:33
  • @Xtremefaith I do not think we can have it similar way as get is implemented since the reflection API was not introduced to in Apex unfortunately. It might be necessary to re-construct the whole object, and store the type somehow. I have no idea at the moment how to do it
    – kurunve
    Commented Oct 15, 2022 at 21:03
  • 1
    @kurunve I can't quite remember the context I needed this for but it's been some time so I'm not sure. I believe the snippet I provided above is the closest I got. Commented Aug 31, 2023 at 16:25
17

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.

You must log in to answer this question.

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