生成地图来自 POJO

发布于 2024-09-09 07:43:29 字数 126 浏览 2 评论 0 原文

我有一个 POJO 和一个(当前尚未构建)将返回它的列表的类。我想自动生成 POJO 作为地图访问所需的代码。这是个好主意吗?是否可以自动执行?我是否需要为每个我想以这种方式处理的 POJO 手动执行此操作?

谢谢, 安迪

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. Is this a good idea, is it possible to do automatically, and do I need to do this manually for every POJO I want to treat this way?

Thanks,
Andy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十级心震 2024-09-16 07:43:29

您可以使用 Commons BeanUtils BeanMap 为此。

Map map = new BeanMap(someBean);

更新:由于 Android 中存在一些明显的库依赖问题,这不是一个选项,这里有一个基本的启动示例,说明如何在 反射 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;
}

如果 java.beans API 可用,那么你可以这样做:

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;
}

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;
}
信仰 2024-09-16 07:43:29

这是我自己的实现,没有任何依赖。它不是复制对象状态,而是在 pojo 上实现实时 Map。 Android 不支持 java .beans,但您可以使用 openbeans 代替。

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);
        }
    }
}

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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文