Convert Figma logo to code with AI

mapstruct logomapstruct

An annotation processor for generating type-safe bean mappers

7,431
989
7,431
480

Top Related Projects

Intelligent object mapping

1,314

Simpler, better and faster Java bean mapping framework

2,102

Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another.

Quick Overview

MapStruct is an open-source Java-based code generator for bean mappings. It simplifies the implementation of mappings between Java bean types, generating type-safe and performant mapping code at compile time. MapStruct reduces the need for manual mapping code, improving maintainability and reducing errors.

Pros

  • Compile-time code generation, ensuring type safety and early error detection
  • High performance due to generated code, avoiding reflection at runtime
  • Easy integration with popular frameworks like Spring and CDI
  • Supports custom mapping methods and expressions for complex scenarios

Cons

  • Learning curve for advanced features and customizations
  • Requires additional build configuration and annotation processing
  • May increase compilation time for large projects
  • Limited support for dynamic mapping scenarios

Code Examples

  1. Basic mapping between two classes:
@Mapper
public interface CarMapper {
    CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);

    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}
  1. Mapping with custom method:
@Mapper
public abstract class UserMapper {
    @Mapping(target = "fullName", expression = "java(fullName(user))")
    public abstract UserDto userToUserDto(User user);

    protected String fullName(User user) {
        return user.getFirstName() + " " + user.getLastName();
    }
}
  1. Mapping with multiple source parameters:
@Mapper
public interface OrderMapper {
    @Mapping(source = "order.customer.name", target = "customerName")
    @Mapping(source = "order.orderDate", target = "date")
    @Mapping(source = "payment.amount", target = "totalAmount")
    OrderSummaryDto orderAndPaymentToSummary(Order order, Payment payment);
}

Getting Started

  1. Add MapStruct dependencies to your project (e.g., using Maven):
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.5.Final</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
  1. Create a mapper interface with the @Mapper annotation:
@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDto userToUserDto(User user);
}
  1. Use the generated mapper in your code:
User user = new User("John", "Doe");
UserDto userDto = UserMapper.INSTANCE.userToUserDto(user);

Competitor Comparisons

Intelligent object mapping

Pros of ModelMapper

  • Runtime-based mapping, allowing for dynamic and flexible configurations
  • Supports deep mapping and flattening of object graphs
  • Minimal configuration required for simple use cases

Cons of ModelMapper

  • Performance overhead due to reflection-based mapping
  • Less compile-time safety compared to MapStruct
  • May require more manual configuration for complex mappings

Code Comparison

ModelMapper:

ModelMapper modelMapper = new ModelMapper();
DestinationObject destObject = modelMapper.map(sourceObject, DestinationObject.class);

MapStruct:

@Mapper
public interface MyMapper {
    DestinationObject map(SourceObject source);
}
MyMapper mapper = Mappers.getMapper(MyMapper.class);
DestinationObject destObject = mapper.map(sourceObject);

ModelMapper uses a runtime-based approach, allowing for quick setup and flexibility. MapStruct, on the other hand, generates mapping code at compile-time, providing better performance and type safety.

While ModelMapper excels in simplicity and dynamic mapping scenarios, MapStruct offers superior performance and compile-time checks. The choice between the two depends on project requirements, with ModelMapper being suitable for rapid development and MapStruct for larger, performance-critical applications.

1,314

Simpler, better and faster Java bean mapping framework

Pros of Orika

  • Runtime-based mapping, allowing for dynamic configuration
  • Supports deep mapping and complex object graphs
  • Built-in support for bidirectional mapping

Cons of Orika

  • Slower performance compared to compile-time mappers
  • Potential for runtime errors due to dynamic mapping
  • Less type-safe than compile-time alternatives

Code Comparison

Orika:

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Source.class, Destination.class)
    .field("sourceField", "destField")
    .byDefault()
    .register();
MapperFacade mapper = mapperFactory.getMapperFacade();
Destination dest = mapper.map(source, Destination.class);

MapStruct:

@Mapper
public interface MyMapper {
    @Mapping(source = "sourceField", target = "destField")
    Destination sourceToDestination(Source source);
}

Destination dest = myMapper.sourceToDestination(source);

MapStruct generates compile-time mapping code, offering better performance and type safety. It integrates well with dependency injection frameworks and provides clear compile-time error messages. However, it requires more setup and may be less flexible for dynamic mapping scenarios. Orika, being runtime-based, offers more flexibility but at the cost of performance and potential runtime errors.

2,102

Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another.

Pros of Dozer

  • Runtime mapping configuration allows for dynamic changes
  • Supports deep mapping and recursive mapping out of the box
  • More flexible with handling null values and default mappings

Cons of Dozer

  • Slower performance due to reflection-based mapping
  • More verbose configuration, especially for XML-based setup
  • Steeper learning curve for complex mappings

Code Comparison

MapStruct:

@Mapper
public interface CarMapper {
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}

Dozer:

<mapping>
  <class-a>com.example.Car</class-a>
  <class-b>com.example.CarDto</class-b>
  <field>
    <a>numberOfSeats</a>
    <b>seatCount</b>
  </field>
</mapping>

MapStruct generates compile-time mapping code, resulting in better performance and earlier error detection. It uses a more concise annotation-based configuration, making it easier to set up and maintain for most use cases.

Dozer, on the other hand, offers more flexibility for complex scenarios and runtime configuration changes. However, this comes at the cost of performance and a more verbose setup process.

Choose MapStruct for simpler, performance-critical mappings, and consider Dozer for highly dynamic or complex mapping requirements where runtime flexibility is crucial.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

MapStruct - Java bean mappings, the easy way!

Latest Stable Version Latest Version License

Build Status Coverage Status

What is MapStruct?

MapStruct is a Java annotation processor designed to generate type-safe and high-performance mappers for Java bean classes, including support for Java 16+ records. By automating the creation of mappings, MapStruct eliminates the need for tedious and error-prone manual coding. The generator provides sensible defaults and built-in type conversions, allowing it to handle standard mappings effortlessly, while also offering flexibility for custom configurations or specialized mapping behaviors. With seamless integration into modern Java projects, MapStruct can map between conventional beans, records, and even complex hierarchies, making it an adaptable tool for diverse Java applications.

Compared to mapping frameworks working at runtime, MapStruct offers the following advantages:

  • Fast execution by using plain method invocations instead of reflection
  • Compile-time type safety. Only objects and attributes mapping to each other can be mapped, so there's no accidental mapping of an order entity into a customer DTO, etc.
  • Self-contained code—no runtime dependencies
  • Clear error reports at build time if:
    • mappings are incomplete (not all target properties are mapped)
    • mappings are incorrect (cannot find a proper mapping method or type conversion)
  • Easily debuggable mapping code (or editable by hand—e.g. in case of a bug in the generator)

To create a mapping between two types, declare a mapper interface like this:

@Mapper
public interface CarMapper {

    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    @Mapping(target = "seatCount", source = "numberOfSeats")
    CarDto carToCarDto(Car car);
}

At compile time MapStruct will generate an implementation of this interface. The generated implementation uses plain Java method invocations for mapping between source and target objects, i.e. no reflection is involved. By default, properties are mapped if they have the same name in source and target, but you can control this and many other aspects using @Mapping and a handful of other annotations.

Requirements

MapStruct requires Java 1.8 or later.

Using MapStruct

MapStruct works in command line builds (plain javac, via Maven, Gradle, Ant, etc.) and IDEs.

For Eclipse, a dedicated plug-in is in development (see https://github.com/mapstruct/mapstruct-eclipse). It goes beyond what's possible with an annotation processor, providing content assist for annotation attributes, quick fixes and more.

For IntelliJ the plug-in is available within the IntelliJ marketplace (see https://plugins.jetbrains.com/plugin/10036-mapstruct-support).

Maven

For Maven-based projects, add the following to your POM file in order to use MapStruct (the dependencies are available at Maven Central):

...
<properties>
    <org.mapstruct.version>1.6.3</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.13.0</version>
            <configuration>
                <source>17</source>
                <target>17</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

Gradle

For Gradle, you need something along the following lines:

plugins {
    ...
    id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}

dependencies {
    ...
    implementation 'org.mapstruct:mapstruct:1.6.3'

    annotationProcessor 'org.mapstruct:mapstruct-processor:1.6.3'
    testAnnotationProcessor 'org.mapstruct:mapstruct-processor:1.6.3' // if you are using mapstruct in test code
}
...

If you don't work with a dependency management tool, you can obtain a distribution bundle from Releases page.

Documentation and getting help

To learn more about MapStruct, refer to the project homepage. The reference documentation covers all provided functionality in detail. If you need help please ask it in the Discussions.

Building from Source

MapStruct uses Maven for its build. Java 21 is required for building MapStruct from source. To build the complete project, run

./mvnw clean install

from the root of the project directory. To skip the distribution module, run

./mvnw clean install -DskipDistribution=true

Importing into IDE

MapStruct uses the gem annotation processor to generate mapping gems for its own annotations. Therefore, for seamless integration within an IDE annotation processing needs to be enabled.

IntelliJ

Make sure that you have at least IntelliJ 2018.2.x (needed since support for annotationProcessors from the maven-compiler-plugin is from that version). Enable annotation processing in IntelliJ (Build, Execution, Deployment -> Compiler -> Annotation Processors)

Eclipse

Make sure that you have the m2e_apt plugin installed.

Links

Licensing

MapStruct is licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.