org.http4k.format.ConfigurableJacksonCsv.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of http4k-format-jackson-csv Show documentation
Show all versions of http4k-format-jackson-csv Show documentation
Http4k CSV support using Jackson as an underlying engine
package org.http4k.format
import com.fasterxml.jackson.dataformat.csv.CsvMapper
import com.fasterxml.jackson.dataformat.csv.CsvSchema
import org.http4k.asString
import org.http4k.core.Body
import org.http4k.core.ContentType
import org.http4k.core.HttpMessage
import org.http4k.core.with
import org.http4k.lens.BiDiBodyLensSpec
import org.http4k.lens.ContentNegotiation
import org.http4k.lens.Meta
import org.http4k.lens.ParamMeta.ObjectParam
import org.http4k.lens.httpBodyRoot
import java.io.StringWriter
import kotlin.reflect.KClass
open class ConfigurableJacksonCsv(val mapper: CsvMapper, val defaultContentType: ContentType = ContentType.TEXT_CSV) {
inline fun defaultSchema(): CsvSchema = mapper.schemaFor(T::class.java).withHeader()
fun writerFor(type: KClass, schema: CsvSchema): (List) -> String = { body: List ->
StringWriter().use { stringWriter ->
mapper.writerFor(type.java).with(schema).writeValues(stringWriter).use {
it.writeAll(body)
}
stringWriter
}.toString()
}
fun readerFor(type: KClass, schema: CsvSchema): (String) -> List {
val reader = mapper.readerFor(type.java).with(schema)
return { body: String ->
reader.readValues(body).readAll()
}
}
inline fun writeCsv(input: List, schema: CsvSchema = defaultSchema()): String {
val writer = writerFor(T::class, schema)
return writer(input)
}
inline fun readCsv(input: String, schema: CsvSchema = defaultSchema()): List {
val reader = readerFor(T::class, schema)
return reader(input)
}
/**
* Convenience function to write the object as CSV to the message body and set the content type.
*/
inline fun R.csv(t: List): R = with(Body.auto().toLens() of t)
/**
* Convenience function to read an object as CSV from the message body.
*/
inline fun HttpMessage.csv(): List = Body.auto().toLens()(this)
inline fun Body.Companion.auto(
description: String? = null,
contentNegotiation: ContentNegotiation = ContentNegotiation.None
) = autoBody(description, contentNegotiation)
inline fun autoBody(
description: String? = null,
contentNegotiation: ContentNegotiation = ContentNegotiation.None,
contentType: ContentType = defaultContentType,
schema: CsvSchema = defaultSchema()
): BiDiBodyLensSpec> {
val reader = readerFor(T::class, schema)
val writer = writerFor(T::class, schema)
return httpBodyRoot(
listOf(Meta(true, "body", ObjectParam, "body", description, emptyMap())),
contentType,
contentNegotiation
)
.map({ it.payload.asString() }, { Body(it) })
.map(reader, writer)
}
}