在 Kotlin 类中使用泛型解析 CSV

Use Generics in Kotlin class for parsing CSV

提问人:Satyam 提问时间:3/24/2023 更新时间:3/24/2023 访问量:241

问:

我在 kotlin 代码中使用 CSVMapper 来解析 CSV 文件。

下面是一个示例代码:

data class UserDto(name: String): Serializable {
}

class CSVMigrator {
    private val csvFile: String
    private val csvMapper = CsvMapper().registerModule(
        KotlinModule.Builder()
            .withReflectionCacheSize(512)
            .configure(KotlinFeature.NullToEmptyCollection, false)
            .configure(KotlinFeature.NullToEmptyMap, false)
            .configure(KotlinFeature.NullIsSameAsDefault, false)
            .configure(KotlinFeature.StrictNullChecks, false)
            .build()
    )

    public constructor(filePath: String) {
        this.csvFile = filePath
    }

    private inline fun <reified T> getIterator(reader: Reader): MappingIterator<T>? {
        val schema = CsvSchema
            .emptySchema()
            .withLineSeparator("\n")
            .withColumnSeparator(',')
            .withQuoteChar('"')
            .withHeader()

        return csvMapper
            .readerFor(T::class.java)
            .without(StreamReadFeature.AUTO_CLOSE_SOURCE)
            .with(schema)
            .readValues<T>(reader)
    }

    fun readFromFile() {
        FileReader(csvFile).use { reader ->
            val iterator = getIterator<UserDto>(reader)
            if (iterator != null) {

                var data = mutableListOf<UserDto>()
                while (iterator.hasNext()) {
                    try {
                        val lineElement = iterator.next()
                        print(lineElement)
                    } catch (e: RuntimeJsonMappingException) {
                        println("Iterator Exception: " + e.localizedMessage)
                    }
                }
            }
        }
    }
}

在上面的代码中,我对 UserDto 类进行了硬编码,以将 CSV 解析为模型。 但是我想使这个类成为通用的(如下面的代码所示),以便我可以根据数据类解析任何CSV。

class CSVMigrator<X: Serializable> {
}

我想在任何地方使用泛型类“X”更改 UserDto。
当我将数据类替换为行中的“X”时,出现以下错误
val iterator = getIterator<X>(reader)

错误是

Cannot use 'X' as reified type parameter. Use a class instead.
Kotlin 解析 泛型 csv-parser csvmapper

评论


答:

1赞 Sweeper 3/24/2023 #1

类类型参数无法重新定义,因此不能将它们传递给具有特定类型参数的泛型方法。

您应该将 in 或 if 本身存储为泛型类型。然后编写一个非具体化的版本,并将其传递给 take / 的另一个重载。Class<X>CSVMigratorTypeReferenceXgetIteratorreaderForClass<T>TypeReference

class CSVMigrator<X: Serializable>(
    val clazz: Class<X>,
//  or:
//  val typeReference: TypeReference<X>,
)
private fun <T> getIterator(
    reader: Reader,
    clazz: Class<T>,
//  or:
//  typeReference: TypeReference<T>,
): MappingIterator<T>? {
    val schema = CsvSchema
        .emptySchema()
        .withLineSeparator("\n")
        .withColumnSeparator(',')
        .withQuoteChar('"')
        .withHeader()

    return csvMapper
        .readerFor(clazz /* or typeReference */)
        .without(StreamReadFeature.AUTO_CLOSE_SOURCE)
        .with(schema)
        .readValues<T>(reader)
}

用法:

val iterator = getIterator(this.clazz /* or this.typeReference */)

创建 时,传入 或 。CSVMigratorClassTypeReference

CSVMigrator(UserDto::class.java)
// or: (not sure if Jackson for Kotlin has an easier to create a TypeReference)
CSVMigrator(object: TypeReference<SomeGenericType<String>>() {})