The question is how to map an array of JSON objects to a java.util.Map
where each key would be some specified property of an object and the value is the object itself.
JSON:
{"items": [{"field1": 1, "field2": "Hello"}, {"field1": 2, "field2":"World"}]}
Java POJO:
public class Storage {
private Map<Integer, Item> items;
}
public class Item {
private Integer field1;
private String field2;
}
So is there a some way to specify to ObjectMapper
that it should use field1
property of each JSON object as key when deserializing array of items to the Map
?
We need to use the JSON-lib library for serializing and de-serializing a Map in JSON format. Initially, we can create a POJO class and pass this instance as an argument to the put() method of Map class and finally add this map instance to the accumulateAll() method of JSONObject.
We can easily convert JSON data into a map because the JSON format is essentially a key-value pair grouping and the map also stores data in key-value pairs. Let's understand how we can use both JACKSON and Gson libraries to convert JSON data into a Map.
You can map the data types of your business model into JSON by using the examples. Data in JSON is either an object or an array. A JSON object is an unordered collection of names and values. A JSON array is an ordered sequence of values.
map() creates a new array from calling a function for every array element. map() calls a function once for each element in an array. map() does not execute the function for empty elements. map() does not change the original array.
How to deserialize a JSON string
You can use Jackson to deserialize a JSON string:
For example if you have class Foo
public class Foo {
private Bar[] items;
// Constructor / Getters & Setters
}
And that class has an array of class Bar
public class Bar {
private int field1;
private String field2;
// Constructor / Getters & Setters
}
Where the field names match those in your JSON string then you can do the following to convert it:
String jsonString = "{\"items\": [{\"field1\": 1, \"field2\": \"Hello\"}, {\"field1\": 2, \"field2\":\"World\"}]}";
ObjectMapper mapper = new ObjectMapper();
Foo foo = mapper.readValue(jsonString, Foo.class);
If you are using Maven, the following dependency would be required in your pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
Approaches to solve your problem:
Option 1 - Custom Deserializer
Write a custom JsonDeserializer
to deserialize your JSON string into a Storage
object with a field items
of type Map<String,Item>
public class CustomDeserializer extends JsonDeserializer<Storage> {
@Override
public Storage deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
Map<Integer, Item> map = new HashMap<>();
ObjectCodec oc = jsonParser.getCodec();
JsonNode rootNode = oc.readTree(jsonParser);
JsonNode items = rootNode.get("items");
for (int i = 0; i < items.size(); i++) {
JsonNode childNode = items.get(i);
Item item = new Item(childNode.get("field1").asInt(), childNode.get("field2").asText());
map.put(item.getField1(), item);
}
return new Storage(map);
}
}
You would then annotate your Storage
class with the following:
@JsonDeserialize(using = CustomDeserializer.class)
Your Storage
class would look something like;
@JsonDeserialize(using = CustomDeserializer.class)
public class Storage {
private Map<Integer, Item> items;
public Storage(Map<Integer, Item> map) {
this.items = map;
}
...
}
Option 2 - Create Map post deserialization
Deserialize the JSON string into a Storage
object with an array of Item
as described at the beginning and then construct your Map<Integer, Item>
after.
Hope this helps.
You can create your own custom Serializers/Deserializers to achieve this. Jackson provides a neat way of doing this. Just annotate the Storage class with @JsonDeserialize(using = YourDeserializer.class) and have the logic to convert the json in YourDeserializer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With