MapStruct无法通过带参构造函数映射目标属性问题求助
MapStruct 1.5.2.Final 无法映射不可变类(仅带@JsonCreator构造)的解决办法
问题背景
使用MapStruct 1.5.2.Final时,尝试映射一个仅含@JsonCreator带参构造的不可变类(无Setter方法),编译时报错:
error: Property "a" has no write accessor in class. error: Property "b" has no write accessor in class.
目标类代码如下:
public class Clazz { private final String a; private final String b; @JsonCreator public Clazz( @JsonProperty("a") final String a, @JsonProperty("b") final String b) { this.a = a; this.b = b; } public String getA() { return a; } public String getB() { return b; } }
解决方案
1. 开启编译参数保留 + 配置Mapper
MapStruct需要识别构造函数的参数名才能完成映射,默认编译可能会丢失参数名,需先开启编译参数保留,再配置Mapper:
编译参数配置
- Maven(pom.xml):
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <!-- 适配你的JDK版本 --> <target>1.8</target> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> </plugins> </build> - Gradle(build.gradle):
compileJava { options.compilerArgs << '-parameters' }
Mapper接口配置
在Mapper接口上指定组件模型(按需选择,比如spring、default),如果属性名和构造参数名一致,MapStruct会自动映射;不一致则用@Mapping显式指定:
@Mapper(componentModel = "spring") public interface ClazzMapper { ClazzMapper INSTANCE = Mappers.getMapper(ClazzMapper.class); // 自动映射(参数名与源属性名一致时) Clazz toClazz(SourceDto source); // 显式映射(参数名与源属性名不同时) // @Mapping(target = "a", source = "dtoA") // @Mapping(target = "b", source = "dtoB") // Clazz toClazz(SourceDto source); }
2. 升级MapStruct版本(可选)
如果上述配置无效,可以尝试升级到MapStruct 1.6.x及以上版本,后续版本对@JsonCreator构造的支持更完善,可能无需额外配置即可自动识别。
关键注意点
- 必须开启
-parameters编译选项,否则MapStruct无法关联构造参数和源属性。 - 若构造参数名与源属性名不匹配,一定要用
@Mapping注解明确映射关系。
内容的提问来源于stack exchange,提问作者Rushil Ahuja
相关产品推荐
相关产品推荐

