What is the elegant way to parse a map into an object?

I have a random object and I need to parse Map<String, String>

public class ExternalIncome {

    private Long operationId;

    private OffsetDateTime operationDate;

    private String operationCode;

    private String documentNumber;

    private OffsetDateTime documentDate;

    private String correspondentInn;

    private String correspondentName;

    private String correspondentAccount;
}

I've just created it this way, but I think it's not quite elegant, rather ugly. Also, I need to intercept every iterate of the parsing to hold dynamic fields into Map<String, String> inside of the object.

public static ExternalIncome create(Map<String, String> fields) {
        ExternalIncome externalIncome = new ExternalIncome();
        fields.forEach((k, v) -> {
            switch (k) {
                case "OPER_ID":
                    externalIncome.setOperationId(nullableLong(v));
                    break;
                case "OPER_DATE":
                    externalIncome.setOperationDate(Utils.toOffsetDateTime(v));
                    break;
               etc

Could you help me to find the best way?

Upvotes: 2

Views: 1246

Answers (2)

SergeiTonoian
SergeiTonoian

Reputation: 341

I don't see any elegant solution in your case, but you get rid of switch/case by using map where the key is the field name from the fields map and value is BiDirectionalConsumer. Probably not the best solution, but still. Note: be careful with casts and type conversions.

Let's say you have fields map:

Map<String, String> fields = new HashMap<>();   
fields.put("OPER_ID", "3"); 

You can define the second map with field names and operation you want to perform:

HashMap<String, BiConsumer<ExternalIncome, Object>> fieldsOperations = new HashMap<>();
fieldsOperations.put("OPER_ID", (extIncome, valueToSet) -> 
    extIncome.setOperationId(Long.valueOf((String) valueToSet))); //add as many as you want

And then where you iterate over your map with fields:

ExternalIncome externalIncome = new ExternalIncome();
fields.forEach((k,v) -> {        
    BiConsumer<ExternalIncome, Object> operation = fieldsOperations.get(k);
    if (operation == null) {    
        //add to dynamic fields map    
        return;
    }
    operation.accept(externalIncome, v);    
});

Or you can reconsider your data structure to get rid of the idea to have dynamic fields, but idk if it's possible with your use case.

Upvotes: 1

Misa D.
Misa D.

Reputation: 323

You can do it using Jackson's ObjectMapper class , if you are allowed to use third part library.

final ObjectMapper mapper = new ObjectMapper();
final ExternalIncome income = mapper.convertValue(fields,ExternalIncome.class)

Upvotes: 1

Related Questions