Convert an Object to Map in Java

Learn to convert an Object to a Java Map using different ways provided by Jackson and Gson APIs. It is also possible to use create your own solution using Java reflection, but it is not recommended to reinvent the wheel until the provided solutions do not serve your purpose.

1. Introduction

In this tutorial, we will convert an instance of the following Employee class into a Map. The Employee class has simple types such as String, and new Java types such as LocalDate and Collection types.

We have a List of Role types to further demonstrate the behavior of different solutions. We will see how different solutions convert the nested types in the converted Map.

class Employee {

  private Integer id;
  private String name;
  private LocalDate dateOfBirth;
  private List<String> locations;
  private List<Role> roles;
}

class Role {
  private Integer id;
  private String name;
}

2. Using Jackson

Jackson is a multi-purpose library that supports different types of conversions such as JSON or XML very well. Jackson also supports converting an Object to Map using the following ways:

2.1. Using ObjectMapper.convertValue()

The convertValue() method does two-step conversion from a given value into an instance of the given value type. It first serializes the given value into JSON and then binds JSON data into the value of the given type. But the conversion is more efficient since full serialization does not (need to) occur.

Note that in the following example we are registering the JavaTimeModule class because Jackson does not support new Java 8 Date-time classes, by default.

Employee employee = new Employee(1, "Alex",
        LocalDate.of(1995, 1, 2),
        List.of("Delhi", "Nevada"),
        List.of(new Role(11, "Finance"), new Role(12, "HR")));

System.out.println(convertObjectToMapUsingObjectMapper(employee));

//The conversion method

static Map<String, String> convertObjectToMapUsingObjectMapper(Employee employee) {

  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.registerModule(new JavaTimeModule());
  objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));

  return objectMapper.convertValue(employee, Map.class);
}

The program output.

{
	id=1, 
	name=Alex, 
	dateOfBirth=1995-01-02, 
	locations=[Delhi, Nevada], 
	roles=[
		{id=11, name=Finance}, 
		{id=12, name=HR}
	]
}

Note that this method converts the associated and nested classes (such as Role) also into LinkedHashMap.

2.2. Using JavaPropsMapper to Convert to Properties

Another interesting solution is to convert the Object to Properties. Properties have a flat structure. Even the nested structures and collections convert into flat structure and all fields/values are converted into String. It may be a good solution in some cases.

Employee employee = new Employee(1, "Alex",
        LocalDate.of(1995, 1, 2),
        List.of("Delhi", "Nevada"),
        List.of(new Role(11, "Finance"), new Role(12, "HR")));

System.out.println(convertObjectToMapUsingJavaPropsMapper(employee));

//The conversion method

static Properties convertObjectToMapUsingJavaPropsMapper(Employee employee) throws IOException {

  JavaPropsMapper mapper = new JavaPropsMapper();
  mapper.registerModule(new JavaTimeModule());
  mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));

  Properties properties = mapper.writeValueAsProperties(employee);
  return properties;
}

The program output.

{
	id=1, 
	name=Alex, 
	dateOfBirth=1995-01-02, 
	locations.1=Delhi, 
	locations.2=Nevada, 
	roles.1.id=11, 
	roles.1.name=Finance, 
	roles.2.id=12, 
	roles.2.name=HR
}

Let us check out the object hierarchy in the debugger.

3. Using Gson’s TypeToken

If our project is already having Gson dependency in the application, we can consider using Gson.fromJson() to convert object to JSON and the converting the JSON to HashMap in the second step.

This technique uses full serialization and deserialization, so it may not give a better performance than Jackson. Use Gson when using Jackson is not possible for some reason.

Employee employee = new Employee(1, "Alex",
        LocalDate.of(1995, 1, 2),
        List.of("Delhi", "Nevada"),
        List.of(new Role(11, "Finance"), new Role(12, "HR")));

System.out.println(convertObjectToMapUsingGson(employee));

static Map<String, String> convertObjectToMapUsingGson(Employee employee) {
  Gson gson = new GsonBuilder()
      .registerTypeAdapter(LocalDate.class, new LocalDateAdapter())
      .create();

  return gson.fromJson(gson.toJson(employee),
      new TypeToken<HashMap<String, Object>>() {
      }.getType()
  );
}

The program output.

{
	id=1.0, 
	name=Alex, 
	dateOfBirth=1995-01-02, 
	locations=[Delhi, Nevada], 
	roles=[
		{id=11.0, name=Finance}, 
		{id=12.0, name=HR}
	]
}

There are primarily two differences between conversion using Gson and Jackson.

  • Gson, by default, converts all number values to Double type.
  • Gson uses LinkedTreeMap for nested classes in place of LinkedHashMap used by Jackson.

4. Using Reflection

Another possible method, though not recommended, is reflection. Using reflection, we must write all the logic by ourselves, and thus there are chances of errors. If you adopt this approach, make sure to test it well before deploying it into production.

The following is a very basic snippet for a simple POJO class that relies on getting the value of a field by its name. We can tweak the method to fetch the value by its getter if there is such a requirement.

public static Map<String, Object> toKeyValuePairs(Object instance) {

  return Arrays.stream(Employee.class.getDeclaredFields())
      .collect(Collectors.toMap(
          Field::getName,
          field -> {
            try {
              Object result = null;
              field.setAccessible(true);
              result = field.get(instance);
              return result != null ? result : "";
            } catch (Exception e) {
              return "";
            }
          }));
}

The program output.

{
	id=1,
	name=Alex, 
	dateOfBirth=1995-01-02, 
	locations=[Delhi, Nevada], 
	roles=[
		Role(id=11, name=Finance), 
		Role(id=12, name=HR)
	]
}

We can verify the map structure in the next diagram. It has the nested classes untouched because we are not accessing them or processing them in our logic. If you need to process them in your application then further expand the logic in toKeyValuePairs() method.

5. Conclusion

This Java tutorial taught us to convert a given Java object into a Map using different solutions. By looking at all solutions, Jackson seems the best solution in terms of ease and performance and is recommended approach in most cases.

For creating flat structures, we can convert Object to Properties using JavaPropsMapper.

Using Gson is quite similar to Jackson, but it does not provide any additional benefit, rather all numbers are converted to Double which may not a desirable situation in some cases. So use it when you cannot use Jackson.

Finally, reflection gives total control into your hand, and you must write every possible usecase/condition yourself.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode