如何在保留类型的前提下将POJO转换为Map?
解决POJO转Map保留原始类型的简便方法
这个问题我之前也遇到过!ObjectMapper默认处理Timestamp这类特殊类型时,确实会自动转成字符串或者时间戳Long,没法保留原始类型。不过不用自己写反射,有几个现成的工具可以直接搞定:
1. 使用Spring的BeanWrapper(推荐,无额外依赖如果已经用Spring)
Spring框架自带的BeanWrapper已经帮我们封装好了反射逻辑,能直接获取POJO属性的原始类型值,完全不用自己写复杂的反射代码。
示例代码:
import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import java.util.HashMap; import java.util.Map; public class PojoMapConverter { public static Map<String, Object> pojoToMap(Object pojo) { BeanWrapper beanWrapper = new BeanWrapperImpl(pojo); Map<String, Object> resultMap = new HashMap<>(); // 遍历所有属性描述符,跳过class属性 for (String propertyName : beanWrapper.getPropertyDescriptors()) { if (!"class".equals(propertyName)) { resultMap.put(propertyName, beanWrapper.getPropertyValue(propertyName)); } } return resultMap; } }
用这个方法转换后,POJO里的Timestamp属性在Map里还是Timestamp类型,和原对象完全一致。
2. 使用Apache Commons PropertyUtils
如果你项目里已经引入了Apache Commons BeanUtils依赖,PropertyUtils.describe()方法可以直接返回保留原始类型的Map:
示例代码:
import org.apache.commons.beanutils.PropertyUtils; import java.util.Map; public class PojoMapConverter { public static Map<String, Object> pojoToMap(Object pojo) throws Exception { Map<String, Object> resultMap = PropertyUtils.describe(pojo); // 移除自动生成的class键值对(如果不需要的话) resultMap.remove("class"); return resultMap; } }
这个方法的返回值类型完全匹配POJO的属性类型,不过要注意它会抛出检查型异常,需要你手动处理或者向上抛出。
3. 自定义Jackson配置(稍复杂但适合纯Jackson场景)
如果不想引入其他依赖,也可以通过配置Jackson的ObjectMapper来保留原始类型。你需要自定义序列化器,让Timestamp这类类型直接以原始对象形式输出:
示例代码:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import java.sql.Timestamp; public class PojoMapConverter { public static Map<String, Object> pojoToMap(Object pojo) throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 为Timestamp自定义序列化器,直接返回原始对象 module.addSerializer(Timestamp.class, new com.fasterxml.jackson.databind.ser.std.StdSerializer<Timestamp>(Timestamp.class) { @Override public void serialize(Timestamp value, com.fasterxml.jackson.core.JsonGenerator gen, com.fasterxml.jackson.databind.SerializerProvider provider) throws java.io.IOException { gen.writeObject(value); } }); mapper.registerModule(module); return mapper.convertValue(pojo, Map.class); } }
不过这种方式需要针对每个特殊类型单独配置,不如前两种工具简便,适合已经重度依赖Jackson且不想加其他依赖的场景。
内容的提问来源于stack exchange,提问作者Sachin C Nambiar
相关产品推荐
相关产品推荐

