![](/img/trans.png)
[英]How convert Bitmap Object to Image Object and vice versa in android 'java'
[英]How to convert a Java object (bean) to key-value pairs (and vice versa)?
假设我有一个非常简单的 java 对象,它只有一些 getXXX 和 setXXX 属性。 该对象仅用于处理值,基本上是一个记录或一个类型安全(和高性能)的映射。 我经常需要将此对象转换为键值对(字符串或类型安全)或从键值对转换为此对象。
除了反射或手动编写代码来进行此转换之外,实现此目的的最佳方法是什么?
一个示例可能是通过 jms 发送此对象,而不使用 ObjectMessage 类型(或将传入消息转换为正确类型的对象)。
许多潜在的解决方案,但让我们再添加一个。 使用Jackson (JSON 处理库)进行“无 json”转换,例如:
ObjectMapper m = new ObjectMapper();
Map<String,Object> props = m.convertValue(myBean, Map.class);
MyBean anotherBean = m.convertValue(props, MyBean.class);
( 此博客条目有更多示例)
您基本上可以转换任何兼容类型:兼容意味着如果您确实从类型转换为 JSON,并从该 JSON 转换为结果类型,则条目将匹配(如果配置正确,也可以忽略无法识别的类型)。
适用于预期的情况,包括映射、列表、数组、原语、类 bean 的 POJO。
总是有 apache commons beanutils但当然它在引擎盖下使用反射
这是一种将Java对象转换为Map的方法
public static Map<String, Object> ConvertObjectToMap(Object obj) throws
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException {
Class<?> pomclass = obj.getClass();
pomclass = obj.getClass();
Method[] methods = obj.getClass().getMethods();
Map<String, Object> map = new HashMap<String, Object>();
for (Method m : methods) {
if (m.getName().startsWith("get") && !m.getName().startsWith("getClass")) {
Object value = (Object) m.invoke(obj);
map.put(m.getName().substring(3), (Object) value);
}
}
return map;
}
这是如何称呼它
Test test = new Test()
Map<String, Object> map = ConvertObjectToMap(test);
代码生成将是我能想到的唯一其他方式。 就我个人而言,我得到了一个通常可重用的反射解决方案(除非代码的那部分绝对是性能关键)。 使用 JMS 听起来有点矫枉过正(额外的依赖,这甚至不是它的意思)。 此外,它可能也在引擎盖下使用反射。
可能是聚会迟到了。 您可以使用 Jackson 并将其转换为 Properties 对象。 这适用于嵌套类,并且如果您想要 for abc=value 中的键。
JavaPropsMapper mapper = new JavaPropsMapper();
Properties properties = mapper.writeValueAsProperties(sct);
Map<Object, Object> map = properties;
如果你想要一些后缀,那就做
SerializationConfig config = mapper.getSerializationConfig()
.withRootName("suffix");
mapper.setConfig(config);
需要添加这个依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-properties</artifactId>
</dependency>
使用 Java 8 你可以试试这个:
public Map<String, Object> toKeyValuePairs(Object instance) {
return Arrays.stream(Bean.class.getDeclaredMethods())
.collect(Collectors.toMap(
Method::getName,
m -> {
try {
Object result = m.invoke(instance);
return result != null ? result : "";
} catch (Exception e) {
return "";
}
}));
}
简单地使用反射和 Groovy :
def Map toMap(object) {
return object?.properties.findAll{ (it.key != 'class') }.collectEntries {
it.value == null || it.value instanceof Serializable ? [it.key, it.value] : [it.key, toMap(it.value)]
}
}
def toObject(map, obj) {
map.each {
def field = obj.class.getDeclaredField(it.key)
if (it.value != null) {
if (field.getType().equals(it.value.class)){
obj."$it.key" = it.value
}else if (it.value instanceof Map){
def objectFieldValue = obj."$it.key"
def fieldValue = (objectFieldValue == null) ? field.getType().newInstance() : objectFieldValue
obj."$it.key" = toObject(it.value,fieldValue)
}
}
}
return obj;
}
使用juffrou-reflect的 BeanWrapper。 它的性能非常好。
以下是将 bean 转换为映射的方法:
public static Map<String, Object> getBeanMap(Object bean) {
Map<String, Object> beanMap = new HashMap<String, Object>();
BeanWrapper beanWrapper = new BeanWrapper(BeanWrapperContext.create(bean.getClass()));
for(String propertyName : beanWrapper.getPropertyNames())
beanMap.put(propertyName, beanWrapper.getValue(propertyName));
return beanMap;
}
我自己开发了 Juffrou。 它是开源的,因此您可以自由使用和修改。 如果您对此有任何疑问,我将非常乐意回答。
干杯
卡洛斯
使用 Spring 时,还可以使用 Spring Integration object-to-map-transformer。 为此,可能不值得将 Spring 添加为依赖项。
有关文档,请在http://docs.spring.io/spring-integration/docs/4.0.4.RELEASE/reference/html/messaging-transformation-chapter.html上搜索“Object-to-Map Transformer”
本质上,它遍历从作为输入给出的对象可达的整个对象图,并从对象上的所有原始类型/字符串字段生成映射。 它可以配置为输出:
这是他们页面上的一个例子:
public class Parent{
private Child child;
private String name;
// setters and getters are omitted
}
public class Child{
private String name;
private List<String> nickNames;
// setters and getters are omitted
}
输出将是:
{person.name=George, person.child.name=Jenna, person.child.nickNames[0]=Bimbo 。 . . 等等}
也可使用反向变压器。
JSON ,例如使用 XStream + Jettison,是一种带有键值对的简单文本格式。 例如,Apache ActiveMQ JMS 消息代理支持它与其他平台/语言进行 Java 对象交换。
当然,有绝对最简单的转换方法——根本没有转换!
不要使用类中定义的私有变量,而是使类只包含一个存储实例值的 HashMap。
然后你的 getter 和 setter 返回并将值设置到 HashMap 中,当需要将它转换为映射时,瞧! ——已经是地图了。
借助一点 AOP 技巧,您甚至可以通过允许您仍然使用特定于每个值名称的 getter 和 setter 来保持 bean 固有的不灵活性,而不必实际编写单独的 getter 和 setter。
您可以使用 java 8 流过滤器收集器属性,
public Map<String, Object> objectToMap(Object obj) {
return Arrays.stream(YourBean.class.getDeclaredMethods())
.filter(p -> !p.getName().startsWith("set"))
.filter(p -> !p.getName().startsWith("getClass"))
.filter(p -> !p.getName().startsWith("setClass"))
.collect(Collectors.toMap(
d -> d.getName().substring(3),
m -> {
try {
Object result = m.invoke(obj);
return result;
} catch (Exception e) {
return "";
}
}, (p1, p2) -> p1)
);
}
您可以使用 Joda 框架:
并利用 JodaProperties。 但是,这确实规定您以特定方式创建 bean,并实现特定接口。 但是,它允许您从特定类返回属性映射,而无需反射。 示例代码在这里:
http://pbin.oogly.co.uk/listings/viewlistingdetail/0e78eb6c76d071b4e22bbcac748c57
如果您不想硬编码对每个 getter 和 setter 的调用,反射是调用这些方法的唯一方法(但这并不难)。
您能否重构有问题的类以使用 Properties 对象来保存实际数据,并让每个 getter 和 setter 对其调用 get/set? 然后你就有了一个非常适合你想做的事情的结构。 甚至还有以键值形式保存和加载它们的方法。
最好的解决方案是使用 Dozer。 你只需要在映射器文件中这样的东西:
<mapping map-id="myTestMapping">
<class-a>org.dozer.vo.map.SomeComplexType</class-a>
<class-b>java.util.Map</class-b>
</mapping>
就是这样,Dozer 负责其余的工作!!!
如果你真的很想要性能,你可以走代码生成路线。
您可以通过自己进行反射并构建一个 mixin AspectJ ITD 来完成此操作。
或者您可以使用 Spring Roo 并制作Spring Roo Addon 。 您的 Roo 插件将执行与上述类似的操作,但每个使用 Spring Roo 的人都可以使用,而您不必使用运行时注释。
我两个都做过。 人们对 Spring Roo 嗤之以鼻,但它确实是最全面的 Java 代码生成。
另一种可能的方式在这里。
BeanWrapper 提供了设置和获取属性值(单独或批量)、获取属性描述符以及查询属性以确定它们是否可读或可写的功能。
Company c = new Company();
BeanWrapper bwComp = BeanWrapperImpl(c);
bwComp.setPropertyValue("name", "your Company");
在 Jackson 库的帮助下,我能够找到 String/integer/double 类型的所有类属性,以及 Map 类中的相应值。 (不使用反射 api! )
TestClass testObject = new TestClass();
com.fasterxml.jackson.databind.ObjectMapper m = new com.fasterxml.jackson.databind.ObjectMapper();
Map<String,Object> props = m.convertValue(testObject, Map.class);
for(Map.Entry<String, Object> entry : props.entrySet()){
if(entry.getValue() instanceof String || entry.getValue() instanceof Integer || entry.getValue() instanceof Double){
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
}
我的 JavaDude Bean 注释处理器生成代码来执行此操作。
http://javadude.googlecode.com
例如:
@Bean(
createPropertyMap=true,
properties={
@Property(name="name"),
@Property(name="phone", bound=true),
@Property(name="friend", type=Person.class, kind=PropertyKind.LIST)
}
)
public class Person extends PersonGen {}
上面生成的超类 PersonGen 包括一个 createPropertyMap() 方法,该方法为使用@Bean 定义的所有属性生成一个 Map。
(请注意,我正在为下一个版本稍微更改 API -- 注释属性将为 defineCreatePropertyMap=true)
你应该写一个通用的转换服务! 使用泛型使其类型自由(因此您可以将每个对象转换为 key=>value 并返回)。
什么领域应该是关键? 从 bean 中获取该字段并将任何其他非瞬态值附加到值映射中。
回来的路还算轻松。 读取 key(x) 并首先写入 key,然后将每个列表条目写回一个新对象。
您可以使用apache commons beanutils获取 bean 的属性名称!
如果涉及到简单的对象树到键值列表的映射,其中键可能是从对象的根元素到被检查的叶子的点状路径描述,很明显,将树转换为键值列表与对象到 xml 映射。 XML 文档中的每个元素都有一个定义的位置,并且可以转换为路径。 因此,我将XStream作为基本且稳定的转换工具,并用自己的实现替换了分层驱动程序和编写器部分。 XStream 还带有一个基本的路径跟踪机制 - 与其他两个结合 - 严格地导致适合该任务的解决方案。
通过使用 Gson,
object
转换为 Json将 Json 转换为地图
retMap = new Gson().fromJson(new Gson().toJson(object), new TypeToken<HashMap<String, Object>>() {}.getType() );
我们可以使用 Jackson 库轻松地将 Java 对象转换为 Map。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
如果在 Android 项目中使用,您可以在您的应用的 build.gradle 中添加 jackson,如下所示:
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
示例实现
public class Employee {
private String name;
private int id;
private List<String> skillSet;
// getters setters
}
public class ObjectToMap {
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
Employee emp = new Employee();
emp.setName("XYZ");
emp.setId(1011);
emp.setSkillSet(Arrays.asList("python","java"));
// object -> Map
Map<String, Object> map = objectMapper.convertValue(emp,
Map.class);
System.out.println(map);
}
}
输出:
{名称=XYZ,id=1011,技能=[python,java]}
添加杰克逊库
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
然后您可以使用对象映射器生成地图。
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.convertValue(
yourJavaObject,
new TypeReference<Map<String, Object>>() {}
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.