列表<List<String>> 映射到列表<String>

List<List<String>> mapped to List<String>

我正在学习如何在 Spring Boot 和 Kotlin 项目中使用 Mapstruct。

我有一个生成的 DTO (ThessaurusDTO),它有一个列表,我需要将其映射到我的模型 (Vocab) 上的一个列表中。

MapStruct 无法自动映射它是有道理的,但我知道第一个列表的大小始终为 1。我无法控制 DTO 模型所属的 API . 我在 documentation 上发现我可以在接口中创建定义默认方法实现,这将松散地转换为 Kotlin 中的普通函数

我的映射器界面:

@Mapper
interface VocabMapper {

    @Mappings(
            // ...
    )
    fun thessaurusToVocab(thessaurusDTO: ThessaurusDTO): Vocab

    fun metaSyns(nestedList: List<List<String>>): List<String> 
             = nestedList.flatten()
}

当我尝试构建时出现以下错误:

VocabMapper.java:16: error: Can't map collection element "java.util.List<java.lang.String>" to "java.lang.String ". Consider to declare/implement a mapping method: "java.lang.String map(java.util.List<java.lang.String> value)".

看起来 mapStruct 仍在尝试自动进行映射,而忽略了我的自定义实现。我是不是遗漏了一些微不足道的东西?

我已经看到通过依赖基于抽象的实现而不是使用接口来解决这个问题。 根据我在网上找到的理解,Kotlin 没有正确地将接口函数转换为 Java 中的默认方法,但实际上生成了一个实现接口的 class。

https://github.com/mapstruct/mapstruct/issues/1577

I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin

From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.

如果这是问题所在,您可以用 @JvmDefault:

注释 metaSyns

Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.

Usages of this annotation require an explicit compilation argument to be specified: either -Xjvm-default=enable or -Xjvm-default=compatibility.

请参阅 link 了解差异,但您可能需要 -Xjvm-default=enable