简体   繁体   中英

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?

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)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM