I have a Java object obj that has attributes obj.attr1, obj.attr2 etc. The attributes are possibly accessed through an extra level of
None of these work for nested properties, object mapper does a fair job except that you have to set all values on all fields you want to see in map and even then you cannot avoid/ignore objects own @Json annotations easily in ObjectMapper basically skip some of the properties. So unfortunately, you have to do something like the following, it is only a draft to just give an idea.
/*
* returns fields that have getter/setters including nested fields as
* field0, objA.field1, objA.objB.field2, ...
* to take care of recursive duplicates,
* simply use a set to track which classes
* have already been traversed
*/
public static void getBeanUtilsNestedFields(String prefix,
Class clazz, List nestedFieldNames) throws Exception {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(clazz);
for(PropertyDescriptor descr : descriptors){
// if you want values, use: descr.getValue(attributeName)
if(descr.getPropertyType().getName().equals("java.lang.Class")){
continue;
}
// a primitive, a CharSequence(String), Number, Date, URI, URL, Locale, Class, or corresponding array
// or add more like UUID or other types
if(!BeanUtils.isSimpleProperty(descr.getPropertyType())){
Field collectionfield = clazz.getDeclaredField(descr.getName());
if(collectionfield.getGenericType() instanceof ParameterizedType){
ParameterizedType integerListType = (ParameterizedType) collectionfield.getGenericType();
Class> actualClazz = (Class>) integerListType.getActualTypeArguments()[0];
getBeanUtilsNestedFields(descr.getName(), actualClazz, nestedFieldNames);
}
else{ // or a complex custom type to get nested fields
getBeanUtilsNestedFields(descr.getName(), descr.getPropertyType(), nestedFieldNames);
}
}
else{
nestedFieldNames.add(prefix.concat(".").concat(descr.getDisplayName()));
}
}
}