MapStruct映射Kotlin布尔类型数据类属性未正确赋值:是Bug还是使用误区?
isActive Boolean Property Between Kotlin Data Classes? This is not a MapStruct bug—it’s a common pitfall caused by the interaction between Kotlin’s property naming conventions and JavaBean standards, which MapStruct relies on for property matching.
Let’s Break Down the Root Cause
Kotlin handles boolean properties starting with is differently when compiling to Java bytecode, following strict JavaBean rules:
- For a Kotlin property
val isActive: Boolean, the compiler generates a getter methodisActive()(instead ofgetIsActive()as you might expect for non-boolean properties). - Crucially, MapStruct interprets the underlying JavaBean property name as
active(stripping theisprefix for boolean types), even though the Kotlin data class constructor uses the fullisActiveparameter name.
When both your source (InObj) and target (OutObj) classes use isActive as the property name:
- MapStruct tries to map the source’s inferred JavaBean property
activeto the target’s JavaBean propertyactive. - But the target’s constructor expects a parameter named
isActive, notactive. MapStruct can’t connect these two, so it falls back to initializing the target property with the defaultfalsevalue instead of pulling it from the source.
When you rename the target property to active:
- The Kotlin compiler generates a JavaBean property named
activewith a gettergetActive(), and the constructor parameter is alsoactive. - MapStruct can now directly match the source’s inferred
activeproperty to the target’sactiveproperty, so the mapping works correctly.
Fixes to Resolve the Issue
You have a few straightforward solutions to fix this:
1. Explicitly Define the Mapping with @Mapping
Tell MapStruct exactly which properties to map, bypassing JavaBean naming inference:
@Mapper interface Mapper { @Mapping(source = "isActive", target = "isActive") fun inToOut(inObj: InObj): OutObj }
This forces MapStruct to use the literal property names from your Kotlin data classes, resulting in correct assignment of isActive from source to target.
2. Use @JvmField to Expose Raw Fields
Annotate your Kotlin properties with @JvmField to make them visible as direct Java fields, instead of relying on JavaBean getters/setters. MapStruct will then use the field names directly:
data class InObj(@JvmField val isActive: Boolean) data class OutObj(@JvmField val isActive: Boolean)
With this, MapStruct recognizes isActive as a field name in both classes and maps them correctly without extra configuration.
3. Align Naming with JavaBean Conventions
If you prefer to avoid annotations, rename your properties to drop the is prefix (e.g., val active: Boolean in both classes). Kotlin will still let you use isActive() as a getter via convention, and MapStruct will handle the mapping seamlessly.
内容的提问来源于stack exchange,提问作者rsobies

