All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kotlinx.serialization.csv.Csv.kt Maven / Gradle / Ivy

package kotlinx.serialization.csv

import kotlinx.serialization.*
import kotlinx.serialization.csv.config.CsvBuilder
import kotlinx.serialization.csv.config.CsvConfig
import kotlinx.serialization.csv.decode.CsvReader
import kotlinx.serialization.csv.decode.RootCsvDecoder
import kotlinx.serialization.csv.decode.StringSource
import kotlinx.serialization.csv.encode.RootCsvEncoder
import kotlinx.serialization.modules.SerializersModule

/**
 * The main entry point to work with CSV serialization.
 *
 * It is typically used by constructing an application-specific instance, with configured CSV-specific behaviour
 * and, if necessary, registered in [SerializersModule] custom serializers.
 * `Csv` instance can be configured in its `Csv {}` factory function using [CsvBuilder].
 * For demonstration purposes or trivial usages, Csv [companion][Csv.Default] can be used instead.
 *
 * Then constructed instance can be used either as regular [SerialFormat] or [StringFormat].
 */
@ExperimentalSerializationApi
sealed class Csv(internal val config: CsvConfig) : SerialFormat, StringFormat {

    override val serializersModule: SerializersModule
        get() = config.serializersModule

    /**
     * Serialize [value] into CSV record(s).
     *
     * @param serializer The serializer used to serialize the given object.
     * @param value The [Serializable] object.
     */
    override fun  encodeToString(serializer: SerializationStrategy, value: T): String {
        val result = StringBuilder()
        RootCsvEncoder(this, result).encodeSerializableValue(serializer, value)
        return result.toString()
    }

    /**
     * Parse CSV [string] into [Serializable] object.
     *
     * @param deserializer The deserializer used to parse the given CSV string.
     * @param string The CSV string to parse.
     */
    override fun  decodeFromString(deserializer: DeserializationStrategy, string: String): T {
        val reader = CsvReader(StringSource(string), config)
        val input = RootCsvDecoder(this, reader)
        val result = input.decodeSerializableValue(deserializer)

        require(reader.isDone) { "Reader has not consumed the whole input: $reader" }
        return result
    }

    internal class Impl(config: CsvConfig) : Csv(config)

    /**
     * Standard *Comma Separated Value* format.
     *
     * Settings are:
     * - [CsvConfig.delimiter] = `','`
     * - [CsvConfig.quoteChar] = `'"'`
     * - [CsvConfig.recordSeparator] = `"\n"`
     * - [CsvConfig.ignoreEmptyLines] = `true`
     */
    companion object Default : Csv(CsvConfig.Default) {

        /**
         * [RFC 4180](http://tools.ietf.org/html/rfc4180) *Comma Separated Value* format.
         *
         * Settings are:
         * - [CsvConfig.delimiter] = `','`
         * - [CsvConfig.quoteChar] = `'"'`
         * - [CsvConfig.recordSeparator] = `"\r\n"`
         * - [CsvConfig.ignoreEmptyLines] = `false`
         */
        val Rfc4180: Csv
            get() = Impl(CsvConfig.Rfc4180)
    }
}

/**
 * Creates an instance of [Csv] configured from the optionally given [Csv instance][from] and
 * adjusted with [action].
 */
@ExperimentalSerializationApi
@Suppress("FunctionName")
fun Csv(from: Csv = Csv.Default, action: CsvBuilder.() -> Unit): Csv {
    val conf = CsvBuilder(from.config).run {
        action()
        build()
    }
    return Csv.Impl(conf)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy