gpt4 book ai didi

java - 将 Java Bean 扁平化为 map

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:50:10 24 4
gpt4 key购买 nike

我一直在转换 Java BeanMap .互联网上有很多资源,但不幸的是,它们都涉及将简单的 beans 转换为 Maps。我的范围更广一些。

有一个简化的例子:

public class MyBean {

private String firstName;
private String lastName;
private MyHomeAddress homeAddress;
private int age;

// getters & setters

}

我的意思是产生Map<String, Object>在这种情况下,对于以下条件为真:

map.containsKey("firstName")
map.containsKey("lastName")
map.containsKey("homeAddress.street") // street is String
map.containsKey("homeAddress.number") // number is int
map.containsKey("homeAddress.city") // city is String
map.containsKey("homeAddress.zipcode") // zipcode is String
map.containsKey("age")

我试过使用 Apache Commons BeanUtils .两种方法 BeanUtils#describe(Object)BeanMap(Object)生成一个“深层”为 1 的 map (我的意思是只有 "homeAddress" 键,持有 MyHomeAddress 对象作为值)。我的方法应该越来越深入地进入对象,直到它遇到原始类型(或字符串),然后它应该停止挖掘并插入 key ,即 "order.customer.contactInfo.home" .

所以,我的问题是:如何轻松完成(或者是否已经存在允许我这样做的项目)?

更新

我已经扩展了 Radiodef 答案以包括 Collections、Maps Arrays 和 Enums:

private static boolean isValue(Object value) {
final Class<?> clazz = value.getClass();
if (value == null ||
valueClasses.contains(clazz) ||
Collection.class.isAssignableFrom(clazz) ||
Map.class.isAssignableFrom(clazz) ||
value.getClass().isArray() ||
value.getClass().isEnum()) {
return true;
}
return false;
}

最佳答案

这是一个简单的反射/递归示例。

您应该知道按照您要求的方式进行转换存在一些问题:

  • 映射键必须是唯一的。
  • Java 允许类将其私有(private)字段命名为与继承类拥有的私有(private)字段相同的名称。

这个例子没有解决这些问题,因为我不确定你想如何解释它们(如果你这样做的话)。如果您的 bean 继承自 Object 以外的东西,您将需要稍微改变一下您的想法。本例只考虑子类的字段。

换句话说,如果你有

public class SubBean extends Bean {

这个例子只会从 SubBean 返回字段。

Java 让我们可以这样做:

package com.acme.util;
public class Bean {
private int value;
}

package com.acme.misc;
public class Bean extends com.acme.util.Bean {
private int value;
}

并不是说任何人都应该这样做,但是如果您想使用 String 作为键,这是一个问题,因为会有两个名为 "value" 的键。

import java.lang.reflect.*;
import java.util.*;

public final class BeanFlattener {
private BeanFlattener() {}

public static Map<String, Object> deepToMap(Object bean) {
Map<String, Object> map = new LinkedHashMap<>();
try {
putValues(bean, map, null);
} catch (IllegalAccessException x) {
throw new IllegalArgumentException(x);
}
return map;
}

private static void putValues(Object bean,
Map<String, Object> map,
String prefix)
throws IllegalAccessException {
Class<?> cls = bean.getClass();

for (Field field : cls.getDeclaredFields()) {
if (field.isSynthetic() || Modifier.isStatic(field.getModifiers()))
continue;
field.setAccessible(true);

Object value = field.get(bean);
String key;
if (prefix == null) {
key = field.getName();
} else {
key = prefix + "." + field.getName();
}

if (isValue(value)) {
map.put(key, value);
} else {
putValues(value, map, key);
}
}
}

private static final Set<Class<?>> VALUE_CLASSES =
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
Object.class, String.class, Boolean.class,
Character.class, Byte.class, Short.class,
Integer.class, Long.class, Float.class,
Double.class
// etc.
)));

private static boolean isValue(Object value) {
return value == null
|| value instanceof Enum<?>
|| VALUE_CLASSES.contains(value.getClass());
}
}

关于java - 将 Java Bean 扁平化为 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25627913/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com