Home > OS >  Get from map, set in object using setter, but for too many fields?
Get from map, set in object using setter, but for too many fields?

Time:03-24

Problem

Consider a Pojo class with a lot of fields. A HashMap is given. Get element from map and set in object (Update operation). Following should be considered:

  • The key name in HashMap and corresponding target field name are not exactly same (see example)
  • If a key is not present in map, don't update corresponding field
  • If key is present, update corresponding field (including updating with null)
  • Do not worry about ClassCastException, map values will be provided with appropriate class type, always.

Example:

Map and Pojo correspondence:

key in HashMap - > field name in Object

  • numberOfItems -> quantity
  • paidAmount -> price
  • adrLine1 -> house
  • adrLine2 -> road
  • adrLine3 -> area
  • adrLine4 -> city
  • ...and 100s more

Pojo class:

private static class MyObject{
    private Integer quantity;
    private Double price;
    private String house;
    private String road;
    private String area;
    private String city;
    ...

    //getter-setters

}

A good old plain approach can be:

private void someMethod(Map<String, Object> updateRequest, MyObject obj){
    if(updateRequest.containsKey("numberOfItems")){
        obj.setQuantity((Integer) updateRequest.get("numberOfItems"));
    }
    if(updateRequest.containsKey("paidAmount")){
        obj.setPrice((Double) updateRequest.get("paidAmount"));
    }
    if(updateRequest.containsKey("adrLine1")){
        obj.setHouse((String) updateRequest.get("adrLine1"));
    }
    if(updateRequest.containsKey("adrLine2")){
        obj.setRoad((String) updateRequest.get("adrLine2"));
    }
    if(updateRequest.containsKey("adrLine3")){
        obj.setArea((String) updateRequest.get("adrLine3"));
    }
    if(updateRequest.containsKey("adrLine4")){
        obj.setCity((String) updateRequest.get("adrLine4"));
    }
    ...
}

But as you can see, this is neither efficient to code, nor comes with a good maintainability.

Something like this would be perfect:

Map<String, Object> updateRequest = //provided
MyObject obj = //provided

List.of(
        Pair.of("numberOfItems", "quantity"),
        Pair.of("paidAmount", "price"),
        Pair.of("adrLine1", "house"),
        Pair.of("adrLine2", "road"),
        Pair.of("adrLine3", "area"),
        Pair.of("adrLine4", "city")
).stream()
.filter(queryPair -> updateRequest.ContainsKey(queryPair.getKey()))
.forEach(queryPair -> obj. set ?? programmatically set field name ?? (updateRequest.get(queryPair.getKey())));

Also feel free to suggest any popular external library that already does this.

CodePudding user response:

Here's a solution that uses lambdas to reify the setters:

Map<String, Object> updateRequest = //provided
MyObject obj = //provided

Map<String, BiConsumer<MyObject, Object>> keyToSetter =
  Map.of(
    "numberOfItems", (o, v) -> o.setQuantity((Integer) v)
    // ...
  );

updateRequest.forEach((k, v) -> keyToSetter.get(k).accept(obj, v));


CodePudding user response:

You can convert your existing myObject instance to a map using ObjectMapper and then merge the two maps. Finally you just have to convert the map to MyObject.

ObjectMapper mapper = new ObjectMapper();
Map<String,Object> myObjectMap = mapper.convertValue(obj, HashMap.class);
inputMap.forEach((k,v)-> myObjectMap.merge(k,v, (v1,v2)-> v2));
MyObject resultObject = mapper.convertValue(myObjectMap , MyObject.class);

Notice the remapping function used above. It only sets value from the inputMap. If no value found for a key, it will keep the value in myObjectMap.

  • Related