Generate Map from POJO

前端 未结 2 2008
别那么骄傲
别那么骄傲 2021-02-04 15:34

I have a POJO, and a (currently not-yet-built) class that will return Lists of it. I\'d like to automatically generate the code necessary for the POJO to be accessed as a Map. I

相关标签:
2条回答
  • You can use Commons BeanUtils BeanMap for this.

    Map map = new BeanMap(someBean);
    

    Update: since that's not an option due to some apparent library dependency problems in Android, here's a basic kickoff example how you could do it with little help of Reflection API:

    public static Map<String, Object> mapProperties(Object bean) throws Exception {
        Map<String, Object> properties = new HashMap<>();
        for (Method method : bean.getClass().getDeclaredMethods()) {
            if (Modifier.isPublic(method.getModifiers())
                && method.getParameterTypes().length == 0
                && method.getReturnType() != void.class
                && method.getName().matches("^(get|is).+")
            ) {
                String name = method.getName().replaceAll("^(get|is)", "");
                name = Character.toLowerCase(name.charAt(0)) + (name.length() > 1 ? name.substring(1) : "");
                Object value = method.invoke(bean);
                properties.put(name, value);
            }
        }
        return properties;
    }
    

    If java.beans API were available, then you could just do:

    public static Map<String, Object> mapProperties(Object bean) throws Exception {
        Map<String, Object> properties = new HashMap<>();
        for (PropertyDescriptor property : Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors()) {
            String name = property.getName();
            Object value = property.getReadMethod().invoke(bean);
            properties.put(name, value);
        }
        return properties;
    }
    
    0 讨论(0)
  • 2021-02-04 16:28

    Here's my own implementation without any dependencies. Rather than make a copy of the object's state, it implements a live Map over the pojo. Android doesn't support java.beans, but you can use openbeans instead.

    import java.beans.*;  // Or, import com.googlecode.openbeans.*
    import java.util.*;
    
    public class BeanMap extends AbstractMap<String, Object> {
        private static final Object[] NO_ARGS = new Object[] {};
        private HashMap<String, PropertyDescriptor> properties;
        private Object bean;
    
        public BeanMap(Object bean) throws IntrospectionException {
            this.bean = bean;
            properties = new HashMap<String, PropertyDescriptor>();
            BeanInfo info = Introspector.getBeanInfo(bean.getClass());
            for(PropertyDescriptor property : info.getPropertyDescriptors()) {
                properties.put(property.getName(), property);
            }
        }
    
        @Override public Object get(Object key) {
            PropertyDescriptor property = properties.get(key);
            if(property == null)
                return null;
            try {
                return property.getReadMethod().invoke(bean, NO_ARGS);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override public Object put(String key, Object value) {
            PropertyDescriptor property = properties.get(key);
            try {
                return property.getWriteMethod().invoke(bean, new Object[] {value});
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override public Set<Map.Entry<String, Object>> entrySet() {
            HashSet<Map.Entry<String, Object>> result = new HashSet<Map.Entry<String, Object>>(properties.size() * 2);
            for(PropertyDescriptor property : properties.values()) {
                String key = property.getName();
                Object value;
                try {
                    value = property.getReadMethod().invoke(bean, NO_ARGS);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                result.add(new PropertyEntry(key, value));
            }
            return Collections.unmodifiableSet(result);
        }
    
        @Override public int size() { return properties.size(); }
    
        @Override public boolean containsKey(Object key) { 
            return properties.containsKey(key);
        }
    
        class PropertyEntry extends AbstractMap.SimpleEntry<String, Object> {
            PropertyEntry(String key, Object value) {
                super(key, value);
            }
    
            @Override public Object setValue(Object value) {
                super.setValue(value);
                return BeanMap.this.put(getKey(), value);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题