Vinicius
Vinicius

Reputation: 1154

ModelMapper - simple way to flat an object

I have a source object with a structure like this:

class SourceA {
  int www;
  SourceB sourceB;
}

class SourceB {
  int xxx;
  int yyy;
  int zzz;
}

And the destination:

class Dest {
  int aaa;
  int bbb;
  int ccc;
  int ddd;
}

This is the most direct way to configure the mapping:

ModelMapper mapper = new ModelMapper();

mapper.createTypeMap(SourceA.class, Dest.class)
  .addMapping(SourceA::getWww, Dest::setDdd)
  .addMapping(src -> src.getSourceB().getXxx(), Dest::setAaa)
  .addMapping(src -> src.getSourceB().getYyy(), Dest::setBbb)
  .addMapping(src -> src.getSourceB().getZzz(), Dest::setCcc);

But I'd like to do something like this:

ModelMapper mapper = new ModelMapper();

mapper.createTypeMap(SourceB.class, Dest.class)
  .addMapping(SourceB::getXxx, Dest::setAaa)
  .addMapping(SourceB::getYyy, Dest::setBbb)
  .addMapping(SourceB::getZzz, Dest::setCcc);

mapper.createTypeMap(SourceA.class, Dest.class)
  .addMapping(SourceA::getWww, Dest::setDdd)
  .addMapping(SourceA::getSourceB, ???); // How to reference self here?

And still convert SourceA to Dest in just 1 step, like in the first option:

Dest dest = mapper.map(sourceA, Dest.class);

Obviously this is an oversimplified example, my problem is to create a mapping where at some point I can reference another mapping to the root dest object.

Upvotes: 2

Views: 1121

Answers (1)

Butiri Dan
Butiri Dan

Reputation: 1772

  1. Explicit mapping
    • Convert the nested class and create the partial mapped destination object
    • Mapped the remaining values on the previous destination object
public static void main(String[] args) {
    ModelMapper createTypeMap = new ModelMapper();
    SourceA sourceA = new SourceA();
    SourceB sourceB = new SourceB();

    sourceB.setXxx(1);
    sourceB.setYyy(2);
    sourceB.setZzz(3);
    sourceA.setWww(4);
    sourceA.setSourceB(sourceB);

    Dest dest = createTypeMap.createTypeMap(SourceB.class, Dest.class)
            .addMapping(SourceB::getXxx, Dest::setAaa)
            .addMapping(SourceB::getYyy, Dest::setBbb)
            .addMapping(SourceB::getZzz, Dest::setCcc)
            .map(sourceB);

    createTypeMap.createTypeMap(SourceA.class, Dest.class)
            .addMapping(SourceA::getWww, Dest::setDdd)
            .map(sourceA, dest);

    System.out.println(dest);
}
  1. Implicit mapping, you can use one of the following workarounds
    • Add setter to the destination object to match the source fields
class Dest {

    int xxx;
    int bbb;
    int ccc;
    int ddd;

    public void setWWW(final int xxx) {
        this.xxx = xxx;
    }

    public void setXXX(final int aaa) {
        this.aaa = aaa;
    }

    public void setYYY(final int bbb) {
        this.bbb = bbb;
    }

    public void setZZZ(final int ccc) {
        this.ccc = ccc;
    }
}
  • Or change the destination or source fields names to match each other

then use the following configuration and mapping

ModelMapper modelMapper = new ModelMapper();

modelMapper.getConfiguration()
            .setMatchingStrategy(MatchingStrategies.LOOSE);

dest = modelMapper.map(sourceA, Dest.class);

System.out.println(dest);

Output

Dest{aaa=1, bbb=2, ccc=3, ddd=4}

Upvotes: 2

Related Questions