[JAVA] Bean mapping with MapStruct Part 3

Continuation of the last time

http://qiita.com/kentama/items/09a8573bd5d0831b470e http://qiita.com/kentama/items/55c71ca28f0c5af8d4ed

Type conversion and format

Type conversion can be performed at the time of mapping like int-> String. At that time, the format can also be specified.

Bean


public class Hoge {
    private String date;
    private String number;

   // constructor/getter/setter
}

public class Fuga {
    private LocalDate date;
    private int number;

   // constructor/getter/setter
}

Creating a Mapper

@Mapper
public interface ConversionMapper {
    ConversionMapper INSTANCE = Mappers.getMapper(ConversionMapper.class);

    @Mapping(target = "date", source = "date", dateFormat = "yyyy year MM month dd day") // (1)
    @Mapping(target = "number", source = "number", numberFormat = "#,###") // (2)
    Hoge convert(Fuga fuga);
}

(1) Specify the date format in the dateFormat attribute. (2) Specify the numerical format in the numberFormat attribute.

Run

Fuga fuga = new Fuga(LocalDate.of(2017, 4, 1), 1234567890);
Hoge hoge = ConversionMapper.INSTANCE.convert(fuga);

System.out.println(hoge.getDate()); //April 01, 2017
System.out.println(hoge.getNumber()); // 1,234,567,890

List type conversion

You can also type-convert a list by using @IterableMapping. This time, int-> String is converted and 3 digits are padded with zeros.

Creating a Mapper

@Mapper
public interface ConversionMapper {
    ConversionMapper INSTANCE = Mappers.getMapper(ConversionMapper.class);

    @IterableMapping(numberFormat = "000")
    List<String> zeroPadding(List<Integer> numbers);
}

Run

List<String> numbers = ConversionMapper.INSTANCE.zeroPadding(Arrays.asList(1, 2, 56, 76, 863));
System.out.println(numbers); // [001, 002, 056, 076, 863]

Mapper reuse

You can use other Mapper from Mapper. You can specify a Mapper generated by MapStruct or a Mapper implemented independently.

Bean


public class Hoge {
    private String date;

    // constructor/getter/setter
}

public class Fuga {
    private LocalDate date;

    // constructor/getter/setter
}

Creating a Mapper

This time, create your own Mapper for LocalDate-> String conversion and reuse it.

Original Mapper


public class LocalDateMapper {
    public String asString(LocalDate date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy year MM month dd day");
        return date != null ? date.format(formatter) : null;
    }
}
@Mapper(uses = LocalDateMapper.class) // (1)
public interface InvokingOtherMapper {
    InvokingOtherMapper INSTANCE = Mappers.getMapper(InvokingOtherMapper.class);

    Hoge fugaToHoge(Fuga fuga);
}

(1) Specify the Mapper to be reused in the ʻuses` attribute.

Run

Fuga fuga = new Fuga(LocalDate.of(2017, 4, 1));
Hoge hoge = InvokingOtherMapper.INSTANCE.fugaToHoge(fuga);

System.out.println(hoge.getDate()); //April 01, 2017

Use of Qualifier

You can add annotations to your own mapping logic so that Mapper can use your own mapping logic. Here, as an example, mapping to convert to uppercase and lowercase is performed.

Bean


public class Hoge {
    private String hoge1;
    private String hoge2;

    // constructor/getter/setter
}

public class Fuga {
    public String fuga1;
    public String fuga2;

    // constructor/getter/setter
}

Creating mapping logic

public class Characters {

    public String upperCase(String string) {
        return (string == null) ? null : string.toUpperCase();
    }

    public String lowerCase(String string) {
        return (string == null) ? null : string.toLowerCase();
    }
}

Creating annotations

@Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface CharacterConverter {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ToUpper {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ToLower {
}

Annotation

Add the created annotation to the mapping logic.

@CharacterConverter
public class Characters {

    @ToUpper
    public String upperCase(String string) {
        return (string == null) ? null : string.toUpperCase();
    }

    @ToLower
    public String lowerCase(String string) {
        return (string == null) ? null : string.toLowerCase();
    }
}

Creating a Mapper

@Mapper(uses = Characters.class) // (1)
public interface HogeFugaMapper {
    HogeFugaMapper INSTANCE = Mappers.getMapper(HogeFugaMapper.class);

    @Mapping(target = "hoge1", source = "fuga1", qualifiedBy = { CharacterConverter.class, ToUpper.class }) // (2)
    @Mapping(target = "hoge2", source = "fuga2", qualifiedBy = { CharacterConverter.class, ToLower.class }) // (3)
    Hoge fugaToHoge(Fuga fuga);
}

(1) Specify the mapping logic class (2) (3) Specify the class level of the mapping logic class and the annotation specified at the method level in the qualifiedBy attribute.

Run

Fuga fuga = new Fuga("abc", "XYZ");
Hoge hoge = HogeFugaMapper.INSTANCE.fugaToHoge(fuga);

System.out.println(hoge.getHoge1()); // ABC
System.out.println(hoge.getHoge2()); // xyz

Next time.

Recommended Posts

Bean mapping with MapStruct Part 3
Bean mapping with MapStruct Part 2
Perform bean mapping at high speed using MapStruct
Bean copy using MapStruct
Use fast Mapping library MapStruct with Lombok and Java 11
Java to learn with ramen [Part 1]
REST API test with REST Assured Part 2
Bean mapping useful in Java ModelMapper
Add Bean Validation with Micronaut (Java)
Easy input check with Bean Validation!
Server processing with Java (Introduction part.1)
Reintroduction to Operators with RxJava Part 1