简体   繁体   中英

Converting a nested collection using Dozer

I have a class A which has a nested set of class B:

public class A {
    private Set<B> children;
}

public class B {
    private int value;
}

I also have a class C which has a nested set of class D:

public class C {
    private Set<D> children;
}

public class D {
    private int value;
}

Now given a List of A, how do I convert it to a List of C? Ideally I should not have to supply any mapping hints since I am using generics. For example:

List<A> src = new ArrayList<A>();
// ----- Add some A's to src -----
List<C> dst = mapper.map(src, List<C>.class);

Obviously, the syntax of last line is not correct. What should it be? Also how do I tell Dozer what type of a List or a Set to create?

Thanks.

Naresh

This is actually answered in their FAQ, but it's all the way down in the advanced section for some reason. I don't think this is an advanced topic, I think it's a common thing to want to do. You do it with a collection hint.

When mapping collections, how do I tell Dozer what type of data objects I want in the destination collection?

Hints are supported to handle this use case. Hints are not required if you are using JDK 1.5 Generics because the types can be auto detected by Dozer. But if you are not using generics, to convert a Collection/Array to a Collection/Array with different type objects you can specify a Hint to let Dozer know what type of objects you want created in the destination list. If a Hint is not specified for the destination field, then the destination Collection will be populated with objects that are the same type as the elements in the src Collection.

 <field> <a>someList</a> <b>otherList</b> <b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint> </field> 

That answer shows you how to do it in xml. Here's how you can do it in java code with a Mapping:

import org.dozer.loader.api.BeanMappingBuilder;

import static org.dozer.loader.api.FieldsMappingOptions.hintB;

public class Mapping extends BeanMappingBuilder {
    @Override
    protected void configure() {
        mapping(Subject.class, JsonSubject.class)
                .fields("names", "names", hintB(JsonName.class));
    }
}

The hint tells dozer, "this list of A's should be converted to a list JsonName instances". Here's how you add this mapping to your mapper:

    mapper = new DozerBeanMapper();
    mapper.addMapping(new Mapping());

You should simply expand this list convertion. Dozer convert JavaBeans and such objects, not collections. So, if you want to pass collections, you can create a wrapper like

public class EntityConverter {
    private Mapper mapper;

    public EntityConverter(Mapper mapper) {
        this.mapper = mapper;
    }

    public <F, T> List<T> convert(List<F> fromList, final Class<T> toClass) {
        return Lists.transform(fromList, new Function<F, T>() {
            @Override
            public T apply(F from) {
                return convert(from, toClass);
            }
        });
    }

    public <F, T> T convert(F from, final Class<T> toClass) {
        if (from == null) return null;
        return mapper.map(from, toClass);
    }
}

Note: This code use Guava.

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