Why Converting Java Beans to Maps Often Fails and How to Fix It
This article explains the hidden pitfalls when converting Java Beans to Map objects—such as type loss and incorrect property names caused by JSON libraries, BeanUtils, and CGLIB—and demonstrates reliable solutions using Dubbo's PojoUtils with clear code examples and visual debugging screenshots.
Background
In some business scenarios a Java Bean needs to be converted to a Map, which appears simple but actually contains many hidden pitfalls.
Pitfalls
2.0 Test Object
import lombok.Data;
import java.util.Date;
@Data
public class MockObject extends MockParent {
private Integer aInteger;
private Long aLong;
private Double aDouble;
private Date aDate;
}
@Data
public class MockParent {
private Long parent;
}2.1 JSON deserialization type loss
2.1.1 Problem reproduction
Using JSON frameworks (fastjson, gson, jackson) to convert a Bean to a Map can cause data‑type loss. For example, a Long value smaller than Integer.MAX_VALUE becomes an Integer after deserialization.
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.8</version>
</dependency> import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.Date;
import java.util.Map;
public class JsonDemo {
public static void main(String[] args) {
MockObject mockObject = new MockObject();
mockObject.setAInteger(1);
mockObject.setALong(2L);
mockObject.setADate(new Date());
mockObject.setADouble(3.4D);
mockObject.setParent(3L);
String json = JSON.toJSONString(mockObject);
Map<String,Object> map = JSON.parseObject(json, new TypeReference<Map<String,Object>>(){});
System.out.println(map);
}
}{"parent":3,"ADouble":3.4,"ALong":2,"AInteger":1,"ADate":1657299916477}
2.2 BeanMap property‑name errors
2.2.1 commons‑beanutils BeanMap
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency> import org.apache.commons.beanutils.BeanMap;
import third.fastjson.MockObject;
import java.util.Date;
public class BeanUtilsDemo {
public static void main(String[] args) {
MockObject mockObject = new MockObject();
mockObject.setAInteger(1);
mockObject.setALong(2L);
mockObject.setADate(new Date());
mockObject.setADouble(3.4D);
mockObject.setParent(3L);
BeanMap beanMap = new BeanMap(mockObject);
System.out.println(beanMap);
}
}2.2.2 cglib BeanMap
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.2.12</version>
</dependency> import net.sf.cglib.beans.BeanMap;
import third.fastjson.MockObject;
import java.util.Date;
public class BeanMapDemo {
public static void main(String[] args) {
MockObject mockObject = new MockObject();
mockObject.setAInteger(1);
mockObject.setALong(2L);
mockObject.setADate(new Date());
mockObject.setADouble(3.4D);
mockObject.setParent(3L);
BeanMap beanMap = BeanMap.create(mockObject);
System.out.println(beanMap);
}
}Solution
3.1 Dubbo‑based fix
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.9</version>
</dependency> import org.apache.dubbo.common.utils.PojoUtils;
import third.fastjson.MockObject;
import java.util.Date;
public class DubboPojoDemo {
public static void main(String[] args) {
MockObject mockObject = new MockObject();
mockObject.setAInteger(1);
mockObject.setALong(2L);
mockObject.setADate(new Date());
mockObject.setADouble(3.4D);
mockObject.setParent(3L);
Object generalized = PojoUtils.generalize(mockObject);
System.out.println(generalized);
}
}3.2 How it works
The core method PojoUtils.generalize(Object) recursively walks the object graph, handling enums, arrays, collections, maps and plain beans. It uses ReflectUtils.getPropertyNameFromBeanReadMethod to derive property names from getter methods, which correctly converts getALong() to aLong without the decapitalize bugs of Introspector.
public static Object generalize(Object pojo) {
return generalize(pojo, new IdentityHashMap());
}
private static Object generalize(Object pojo, Map<Object,Object> history) {
if (pojo == null) return null;
if (pojo instanceof Enum) return ((Enum<?>)pojo).name();
// handle arrays, collections, maps, primitives, Class, etc.
// for beans, iterate over public getter methods:
for (Method method : pojo.getClass().getMethods()) {
if (ReflectUtils.isBeanPropertyReadMethod(method)) {
ReflectUtils.makeAccessible(method);
map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method),
generalize(method.invoke(pojo), history));
}
}
// also handle public fields
return map;
}Because the property‑name extraction simply lower‑cases the first character after get or is, it produces the expected aLong, aDate, etc., and avoids the special‑case handling of Introspector.decapitalize that mis‑processes names like URL.
Conclusion
Converting Java Beans to Map objects is fraught with pitfalls: type loss when using JSON libraries and incorrect property‑name resolution in BeanMap implementations. Developers should verify conversion results with small demos, read the source code of the utilities they use, and consider Dubbo’s PojoUtils or a custom reflection‑based approach for reliable results.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
