简体   繁体   中英

Lost content for field with type List<Map<String, String>> when mapping using Orika Mapper

Anyone encountered the same problem for field with type List<Map<String, String>> when mapping? I get no exceptions, but is there anything I need to configure to my mapper?

The situation is I have this object with this field

List<Map<String, String>> aField

contents of aField field are:

[
{
"key1" : "val1",
"key2": "val2"
}
]

when the object is mapped to another object, the content of this field are lost to the newly mapped object, when I try to print, the size of the list is still 1 but the content of map is empty (below):

[
{}
]

I would appreciate any help. Thanks.

The code are as follows:

This is the class to be mapped:

public class SampleClass {
    private List<Map<String, String>> aField = new ArrayList<>();
    private String bField;

    public List<Map<String, String>> getaField() {
        return aField;
    }

    public void setaField(List<Map<String, String>> aField) {
        this.aField = aField;
    }

    public String getbField() {
        return bField;
    }

    public void setbField(String bField) {
        this.bField = bField;
    }
}

then I have a mapper (I'm using spring framework too):

@Component
public class TransactionMapper extends ConfigurableMapper {
}

Somewhere on a controller (for testing purposes):

@Autowired
    TransactionMapper mapper;

    System.out.println("---------------- SAMPLE CLASS ------------- ");
                    SampleClass s1 = new SampleClass();
                    List<Map<String, String>> aField = Lists.newArrayList();
                    Map<String, String> map = new HashMap<>();
                    map.put("key1", "val1");
                    map.put("key2", "val2");
                    aField.add(map);
                    s1.setaField(aField);
                    s1.setbField("Sample text");

                    System.out.println("****** s1 contents ******");
                    System.out.println("--- s1 aField: " + ", list size: " + s1.getaField().size());
                    s1.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
                    System.out.println("--- s1 bField content: " + s1.getbField());
                    System.out.println("****** end of s1 contents ******");

                    SampleClass s2 = new SampleClass();
                    mapper.map(s1, s2);
                    System.out.println("****** s2 contents ******");
                    System.out.println("--- s2 aField: " + ", list size: " + s2.getaField().size());
                    s2.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
                    System.out.println("--- s2 bField content: " + s2.getbField());
                    System.out.println("****** end of s2 contents ******");

                    System.out.println("---------------- SAMPLE CLASS ------------- ");

Output:

****** s1 contents ******
--- s1 aField: , list size: 1
key1:val1
key2:val2
--- s1 bField content: Sample text
****** end of s1 contents ******
****** s2 contents ******
--- s2 aField: , list size: 1
--- s2 bField content: Sample text
****** end of s2 contents ******
---------------- SAMPLE CLASS ------------- 

As you can see, there are no printed contents for the aField of s2.

After making some research, I've found out the following solution:

  • Use CustomMapper instead of ConfigurableMapper.
  • Don't forget to create mapper factory.

First add this to the TransactionMapper class:

public class TransactionMapper extends ConfigurableMapper{

    public TransactionMapper(MapperFactory f) {
        configure(f);
    } 

    public void configure(MapperFactory f) {
        f.classMap(SampleClass.class, SampleClass.class).customize(new CustomMapper<SampleClass, SampleClass>() {
            //Override mapping method and set source fields to destination fields
            @Override
            public void mapAtoB(SampleClass source, SampleClass destination, MappingContext context) {
                destination.setaField(source.getaField());
                destination.setbField(source.getbField());
            }
        }).byDefault().register();
    }
}

Then your main class should look something like this:

...
MapperFactory factory = new DefaultMapperFactory.Builder().build(); //Create the mapper factory
TransactionMapper mapper = new TransactionMapper(factory); //Call the mapper constructor

System.out.println("---------------- SAMPLE CLASS ------------- ");
SampleClass s1 = new SampleClass();
List<Map<String, String>> aField = new ArrayList<Map<String, String>>();
Map<String, String> map = new HashMap<>();
map.put("key1", "val1");
map.put("key2", "val2");
aField.add(map);
s1.setaField(aField);
s1.setbField("Sample text");

System.out.println("****** s1 contents ******");
System.out.println("--- s1 aField: " + ", list size: " + s1.getaField().size());
s1.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
System.out.println("--- s1 bField content: " + s1.getbField());
System.out.println("****** end of s1 contents ******");

SampleClass s2 = mapper.map(s1, SampleClass.class);
System.out.println("****** s2 contents ******");
System.out.println("--- s2 aField: " + ", list size: " + s2.getaField().size());
s2.getaField().get(0).forEach((k, v) -> System.out.println((k + ":" + v)));
System.out.println("--- s2 bField content: " + s2.getbField());
System.out.println("****** end of s2 contents ******");

System.out.println("---------------- SAMPLE CLASS ------------- ");
...

Output:

---------------- SAMPLE CLASS ------------- 
****** s1 contents ******
--- s1 aField: , list size: 1
key1:val1
key2:val2
--- s1 bField content: Sample text
****** end of s1 contents ******
****** s2 contents ******
--- s2 aField: , list size: 1
key1:val1
key2:val2
--- s2 bField content: Sample text
****** end of s2 contents ******
---------------- SAMPLE CLASS ------------- 

Let me know if it worked. If you have any question ask it and I will do my best to answer. If this worked, please mark the answer as the solution so that other people with the same problem know what to do. :)

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