Home » Jackson Java convert between JSON and Map

Jackson Java convert between JSON and Map

  • by

1. Overview

In this article, we will learn to convert between JSON and Map in Java using Jackson library.

To learn more about Jackson, refer to our articles.

By encoding your Java object as a JSON string, you can transfer the Java Map object over a network or store it in a database or a file.

Serialization is converting your Java object in your application to the JSON format, whereas deserialization converts the JSON back into the original Java object.

 ObjectMapper class of Jackson helps you with the serialization and deserialization process in Java. Let’s understand how to configure your Jackson to convert between Map and JSON.

2. Dependencies

To get started, you must add the Jackson library as a dependency in your project.

<dependency> 
   <groupId>com.fasterxml.jackson.core</groupId> 
   <artifactId>jackson-databind</artifactId> 
   <version>2.13.0</version>
</dependency>
Jackson dependencies
Jackson dependencies

This ObjectMapper class is available in the Jackson databind project.

The com.fasterxml.jackson.core.databind library dependency pulls in all other required dependencies into your project:

  • jackson-annotations
  • jackson-core

3. Jackson convert between JSON and Map<String, String>

Let’s see serialization and deserialization between JSON and Map<String, String>.

3.1. Serialization – convert Map<String, String> to a JSON

There is no special configuration required to convert Map<String, String> to JSON. You can simply use the ObjectMapper class to convert the Map to JSON.

For example, the below test method contains a Map of users and their corresponding age.

@Test
void serializeMap_String_String() throws JsonProcessingException {
	Map<String, String> map = new HashMap<>();
	map.put("John", "15");
	map.put("Mike", "25");
	map.put("Jackson", "45");

	ObjectMapper mapper = new ObjectMapper();
	String jsonResult = mapper.writeValueAsString(map);
	System.out.println(jsonResult);
}

If you run the above code, the ObjectMapper converts the Map to JSON and prints the following result:

{"Mike":"25","John":"15","Jackson":"45"}

3.2. Deserialization – convert JSON to Map<String, String>

You can deserialize the JSON with an array of objects to Map<String, String> by using the ObjectMapper's readValue method and passing Map.class as a parameter. However, IDE throws unchecked assignment Map to Map<String, String>.

@Test
void dserializeMap_String_String() throws JsonProcessingException {
	String mapStr = "{\"Mike\":\"25\",\"John\":\"15\",\"Jackson\":\"45\"}";

	ObjectMapper mapper = new ObjectMapper();
	Map<String, String> map = mapper.readValue(mapStr, Map.class);
	for (Map.Entry<String, String> entry : map.entrySet()) {
	    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
	}

/* prints
Key = Mike, Value = 25
Key = John, Value = 15
Key = Jackson, Value = 45
*/
}

Though the above code works fine and provides the expected result, the IDE would show the following warning

Type safety: The expression of type Map needs unchecked conversion to conform to Map

3.2.1. Configure TypeReference for Map<String, String> deserialization

You can prevent the unchecked assignment error by using the TypeReference, a class of Jackson library that allows to provide the type information to Jackson. Therefore, Jackson resolves to the provided type.

@Test
void dserializeMap_String_String() throws JsonProcessingException {
	String mapStr = "{\"Mike\":\"25\",\"John\":\"15\",\"Jackson\":\"45\"}";
	ObjectMapper mapper = new ObjectMapper();

        TypeReference<HashMap<String, String>> typeRef 
            = new TypeReference<HashMap<String, String>>() {};
	Map<String, String> map = mapper.readValue(mapStr, typeRef);

	for (Map.Entry<String, String> entry : map.entrySet()) {
	    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
	}
}
/* prints
Key = Mike, Value = 25
Key = John, Value = 15
Key = Jackson, Value = 45
*/

3.2.2. Configure TypeFactory for Map<String, String> deserialization

Alternatively, you can use the overloaded readValue function that accepts the JavaType as input:

public <T> T readValue(String content, JavaType valueType) throws JsonProcessingException, JsonMappingException

The JavaType is the base class that contains type information for deserializer. To create a JavaType, you first need to get the configured and readily available TypeFactory instance from the ObjectMapper object.

TypeFactory typeFactory = mapper.getTypeFactory();

You can create the MapType (subclass of JavaType) to deserialize the JSON array of objects as a Map object.

typeFactory.constructMapType(HashMap.class, 
				String.class, 
				String.class)
@Test
void dserializeMap_String_String_TypeFactory() throws JsonProcessingException {
	String mapStr = "{\"Mike\":\"25\",\"John\":\"15\",\"Jackson\":\"45\"}";

	ObjectMapper mapper = new ObjectMapper();
	TypeFactory typeFactory = mapper.getTypeFactory();
	Map<String, String> map = mapper.readValue(mapStr, typeFactory.constructMapType(HashMap.class, 
			String.class, 
			String.class));
	for (Map.Entry<String, String> entry : map.entrySet()) {
	    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
	}
}

4. Jackson convert between JSON and Map<String, Object>

Let’s see serialization and deserialization between JSON and Map<String, Object>.

4.1. Serialization – convert Map<String, Object > to a JSON

Here, no special configuration is required to convert Map<String, Object > to JSON. You can simply use the ObjectMapper class to convert the Map to JSON.

For example, the below test method contains an Map of students sorted by their rank.

@Test
void serializeMap_String_Object() throws JsonProcessingException {
	Map<String, Student> map = new HashMap<>();
	Student student = new Student("John", "Smith");
	map.put("First", student);
	Student jack = new Student("Mike", "Jack");
	map.put("Second", jack);

	ObjectMapper mapper = new ObjectMapper();
	String jsonResult = mapper.writeValueAsString(map);
	System.out.println(jsonResult);
	/* prints 

        {"Second":{"firstName":"Mike","lastName":"Jack"},"First":{"firstName":"John","lastName":"Smith"}}
        */
}

4.2. Deserialize to Map<String, Object> from JSON

You can deserialize the JSON with an array of objects to Map<String, Object> by using the ObjectMapper'sreadValue method and passing Map.class as a parameter. However, IDE throws unchecked assignment Map to Map<String, Object>.

@Test
	void dserializeMap_String_Object() throws JsonProcessingException {
		String mapStr = "{\"Second\":{\"firstName\":\"Mike\",\"lastName\":\"Jack\"},\"First\":{\"firstName\":\"John\",\"lastName\":\"Smith\"}}";

		ObjectMapper mapper = new ObjectMapper();

		Map<String, Student> map = mapper.readValue(mapStr, Map.class);
		for (Entry<String, Student> entry : map.entrySet()) {
		    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
		}
	}

If you run the above code, then the ObjectMapper converts the JSON to Map<String, Student> and prints the following result.

Key = Second, Value = {firstName=Mike, lastName=Jack}
Key = First, Value = {firstName=John, lastName=Smith}

Though the above code works fine and provides the expected result, the IDE would show the following warning

Type safety: The expression of type Map needs unchecked conversion to conform to Map

3.2.1. Configure TypeReference for Map<String, Object> deserialization

You can prevent the unchecked assignment error by using the TypeReference, a class of Jackson library that allows providing the type information to Jackson. Therefore, Jackson resolves to the provided type.

@Test
void dserializeMap_String_Object_TypeRef() throws JsonProcessingException {
	String mapStr = "{\"Second\":{\"firstName\":\"Mike\",\"lastName\":\"Jack\"},\"First\":{\"firstName\":\"John\",\"lastName\":\"Smith\"}}";

	ObjectMapper mapper = new ObjectMapper();

        TypeReference<HashMap<String, Student>> typeRef 
            = new TypeReference<HashMap<String, Student>>() {};
	Map<String, Student> map = mapper.readValue(mapStr, typeRef);
	for (Entry<String, Student> entry : map.entrySet()) {
	    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
	}
}
Key = Second, Value = {firstName=Mike, lastName=Jack}
Key = First, Value = {firstName=John, lastName=Smith}

3.2.2. Configure TypeFactory for Map<String, String> deserialization

Alternatively, you can use the overloaded readValue function that accepts the JavaType as input:

public <T> T readValue(String content, JavaType valueType) throws JsonProcessingException, JsonMappingException

The JavaType is the base class that contains type information for deserializer. To create a JavaType, you first need to get the configured and readily available TypeFactory instance from the ObjectMapper object.

TypeFactory typeFactory = mapper.getTypeFactory();

You can create the MapType (subclass of JavaType) to deserialize the JSON array of objects as a Map<String, Student> object.

typeFactory.constructMapType(HashMap.class, 
				String.class, 
				Student.class)
@Test
void dserializeMap_String_Object_TypeFactory() throws JsonProcessingException {
	String mapStr = "{\"Second\":{\"firstName\":\"Mike\",\"lastName\":\"Jack\"},\"First\":{\"firstName\":\"John\",\"lastName\":\"Smith\"}}";

	ObjectMapper mapper = new ObjectMapper();
	TypeFactory typeFactory = mapper.getTypeFactory();
	Map<String, Student> map = mapper.readValue(mapStr, typeFactory.constructMapType(HashMap.class, 
			String.class, 
			Student.class));
	for (Map.Entry<String, Student> entry : map.entrySet()) {
	    System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
	}
}
Key = Second, Value = {firstName=Mike, lastName=Jack}
Key = First, Value = {firstName=John, lastName=Smith}

5. Conclusion

To sum up, we have learned to serialize or deserialize maps using the Jackson library.

Leave a Reply

Your email address will not be published. Required fields are marked *