Java bean mappings, the easy way!

Get started Download

What is it?

MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach.

The generated mapping code uses plain method invocations and thus is fast, type-safe and easy to understand.

Why?

Multi-layered applications often require to map between different object models (e.g. entities and DTOs). Writing such mapping code is a tedious and error-prone task. MapStruct aims at simplifying this work by automating it as much as possible.

In contrast to other mapping frameworks MapStruct generates bean mappings at compile-time which ensures a high performance, allows for fast developer feedback and thorough error checking.

How?

MapStruct is an annotation processor which is plugged into the Java compiler and can be used in command-line builds (Maven, Gradle etc.) as well as from within your preferred IDE.

MapStruct uses sensible defaults but steps out of your way when it comes to configuring or implementing special behavior.


Latest News

Support for builders, mapper constructor injection and much more: MapStruct 1.3.0.Beta1 is out

It’ my pleasure to announce the first Beta release of MapStruct 1.3.

The new release comes with a whole lot of new functionality, e.g.:

  • Mapping of (immutable) objects using builders
  • Constructor injection for Annotation Based component models
  • unmappedSourcePolicy support
  • Support for defaultExpression
  • Limit mapping only to explicitly defined mappings
  • Performance improvement of constant / defaultValue primitive to String mappings

Read more...

Filip Hrisafov Taking Over as MapStruct Project Lead

It’s with great happiness and excitement that I’m announcing that Filip Hrisafov is taking over the role of MapStruct’s project lead!

Really that’s just manifesting the status quo of the last couple of months, during which Filip already was acting in that role effectively. As I’ve been able to contribute less and less time towards MapStruct over the last year, it was about time to pass on the baton to a new lead, with many fresh ideas and a great level of enthusiasm.

Filip joined the team in 2016, sending in a patch for improving our test suite. Since then, he became an invaluable member of the MapStruct community. He implemented several new features and stepped up to help with reviewing pull requests, providing help to new contributors, answering related questions on StackOverflow and even doing the last few releases of the project.

Having had the pleasure of working with Filip over the last years, I’m convinced that going forward he’s the perfect person for leading the project.

Read more...

MapStruct 1.2.0.Final is out

I’m very happy to announce the final version MapStruct 1.2!

After less than a year from the 1.1.0.Final release, 3 Beta and 2 CR releases, MapStruct 1.2.0.Final is finally out :).

Besides bug fixes, the 1.2 release brings some new interesting features:

  • MapStruct can be used with Lombok out of the box
  • Java 8 Stream support
  • Mappings based on public fields
  • Automatic creation of nested mapping methods
  • Mapping methods can take “pass-through” context parameters, addressing different use cases like
    • Passing a locale, timezone or similar to custom mapping methods
    • Keeping track of processed nodes in circular object graphs
  • Target bean factory methods can access a mapping’s source parameter(s)
  • Nested target mappings have been reworked from the ground up
  • Java 9 Compatibility

Read more...

MapStruct in 2 Minutes

The following shows how map two objects using MapStruct.

Let's assume we have a class representing cars (e.g. a JPA entity) and an accompanying data transfer object (DTO).

Both types are rather similar, only the seat count attributes have different names and the type attribute is of a special enum type in the Car class but is a plain string in the DTO.

  • public class Car {
    
        private String make;
        private int numberOfSeats;
        private CarType type;
    
        //constructor, getters, setters etc.
    }
  • public class CarDto {
    
        private String make;
        private int seatCount;
        private String type;
    
        //constructor, getters, setters etc.
    }

The mapper interface

To generate a mapper for creating a CarDto object out of a Car object, a mapper interface needs to be defined:

    1. @Mapper 1
    2. public interface CarMapper {
    3.  
    4. CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 3
    5.  
    6. @Mapping(source = "numberOfSeats", target = "seatCount")
    7. CarDto carToCarDto(Car car); 2
    8. }

The @Mapper annotation 1 marks the interface as mapping interface and lets the MapStruct processor kick in during compilation.

The actual mapping method 2 expects the source object as parameter and returns the target object. Its name can be freely chosen.

For attributes with different names in source and target object, the @Mapping annotation can be used to configure the names.

Where required and possible a type conversion will be executed for attributes with different types in source and target, e.g. the type attribute will be converted from the enumeration type into a string.

Of course there can be multiple mapping methods in one interface, for all of which an implementation will be generated by MapStruct.

An instance of the interface implementation can be retrieved from the Mappers class. By convention, the interface declares a member INSTANCE 3, providing clients access to the mapper implementation.

Using the mapper

Based on the mapper interface, clients can perform object mappings in a very easy and type-safe manner:

  • @Test
    public void shouldMapCarToDto() {
        //given
        Car car = new Car( "Morris", 5, CarType.SEDAN );
    
        //when
        CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
    
        //then
        assertThat( carDto ).isNotNull();
        assertThat( carDto.getMake() ).isEqualTo( "Morris" );
        assertThat( carDto.getSeatCount() ).isEqualTo( 5 );
        assertThat( carDto.getType() ).isEqualTo( "SEDAN" );
    }

Tell me more!

You like what you see? Then check out the reference documentation to learn how to get started with MapStruct and which advanced features there are. In case you need help or want to propose a new feature just drop by on the mapstruct-users group.

You want to contribute to the development of MapStruct? That's great, this page has all the information you need.