@@ -10,19 +10,64 @@ import kotlinx.serialization.encoding.*
1010import kotlinx.serialization.internal.*
1111import kotlinx.serialization.modules.*
1212
13+ /* *
14+ * Transforms a [Serializable] class' properties into a single flat [String] representing the class data
15+ * in the properties format.
16+ *
17+ * If the given class has non-primitive property `d` of arbitrary type `D`, `D` values are inserted
18+ * into the same map; keys for such values are prefixed with string `d.`:
19+ *
20+ * ```
21+ * @Serializable
22+ * class Data(val property1: String)
23+ *
24+ * @Serializable
25+ * class DataHolder(val data: Data, val property2: String)
26+ *
27+ * val string = StringProperties.encodeToString(properties)
28+ * // string contents will be the following:
29+ * """
30+ * property2 = value2
31+ * data.property1 = value1
32+ * """
33+ * ```
34+ *
35+ * If the given class has a [List] property `l`, each value from the list
36+ * would be prefixed with `l.N.`, where N is an index for a particular value.
37+ * [Map] is treated as a `[key,value,...]` list.
38+
39+ * Conversely, this class can convert a properties string into a [Serializable] class instance.
40+ * ```
41+ * @Serializable
42+ * class Data(val property1: String)
43+ *
44+ * @Serializable
45+ * class DataHolder(val data: Data, val property2: String)
46+ *
47+ * val string = """
48+ * property2 = value2
49+ * data.property1 = value1
50+ * """
51+ * val data = StringProperties.decodeToString(string, DataHolder.serializer())
52+ * // data contents will be the following:
53+ * // DataHolder(data = Data(property1 = "value1"), property2 = "value2")
54+ * ```
55+ *
56+ * @param conf A [PropertiesConf] which contain configuration for customising the output string.
57+ */
1358@ExperimentalSerializationApi
1459@Suppress(" UNUSED_PARAMETER" )
1560public sealed class StringProperties (
1661 private val conf : PropertiesConf ,
1762 private val properties : Properties = Properties (conf.serializersModule),
18- ) : SerialFormat by properties {
63+ ) : SerialFormat by properties, StringFormat {
1964
2065 /* *
2166 * Encodes properties from the given [value] to a properties String using the given [serializer].
2267 * `null` values are omitted from the output.
2368 */
2469 @ExperimentalSerializationApi
25- public fun <T > encodeToString (serializer : SerializationStrategy <T >, value : T ): String {
70+ public override fun <T > encodeToString (serializer : SerializationStrategy <T >, value : T ): String {
2671 val map = properties.encodeToMap(serializer, value)
2772 val builder = StringBuilder ()
2873 for ((k, v) in map) {
@@ -45,12 +90,10 @@ public sealed class StringProperties(
4590 * [String] values are converted to respective primitive types using default conversion methods.
4691 * [T] may contain properties of nullable types; they will be filled by non-null values from the [map], if present.
4792 */
48- public fun <T > decodeFromString (deserializer : DeserializationStrategy <T >, string : String ): T {
93+ public override fun <T > decodeFromString (deserializer : DeserializationStrategy <T >, string : String ): T {
4994 val result = mutableMapOf<String , String >()
5095 for (line in string.logicalLines()) {
51- println (" line=`$line `" )
5296 val parsedLine = line.unescaped()
53- println (" parsedLine=`$parsedLine `" )
5497 var keyEnd = parsedLine.length
5598 for (i in parsedLine.indices) {
5699 if (parsedLine[i] in separators) {
@@ -77,8 +120,6 @@ public sealed class StringProperties(
77120
78121 result[parsedLine.substring(0 , keyEnd)] = parsedLine.substring(valueBegin)
79122 }
80- println (result)
81- println (result.keys)
82123 return properties.decodeFromStringMap(deserializer, result)
83124 }
84125
@@ -97,8 +138,8 @@ private class StringPropertiesImpl(conf: PropertiesConf) : StringProperties(conf
97138 * TODO: doc
98139 */
99140@ExperimentalSerializationApi
100- public fun StringProperties (builderAction : PropertiesBuilder .() -> Unit = {}): StringProperties {
101- val builder = PropertiesBuilder (PropertiesConf ())
141+ public fun StringProperties (builderAction : StringPropertiesBuilder .() -> Unit = {}): StringProperties {
142+ val builder = StringPropertiesBuilder (PropertiesConf ())
102143 builder.builderAction()
103144 return StringPropertiesImpl (builder.build())
104145}
@@ -121,13 +162,40 @@ public inline fun <reified T> StringProperties.encodeToString(value: T): String
121162public inline fun <reified T > StringProperties.decodeFromString (propertiesString : String ): T =
122163 decodeFromString(serializersModule.serializer(), propertiesString)
123164
165+ /* *
166+ * Builder of the [StringProperties] instance provided by `StringProperties { ... }` factory function.
167+ */
124168@ExperimentalSerializationApi
125- public class PropertiesBuilder internal constructor(from : PropertiesConf ) {
169+ public class StringPropertiesBuilder internal constructor(from : PropertiesConf ) {
126170
171+ /* *
172+ * A [LineSeparator] to be used for separating lines when encoding to a string.
173+ * Default value is [LineSeparator.LF].
174+ */
127175 public var lineSeparator: LineSeparator = from.lineSeparator
176+
177+ /* *
178+ * A [KeyValueSeparator] to be used for separating keys and values when encoding to a string.
179+ * Default value is [KeyValueSeparator.EQUALS].
180+ */
128181 public var keyValueSeparator: KeyValueSeparator = from.keyValueSeparator
182+
183+ /* *
184+ * A number of spaces to be inserted before the [keyValueSeparator] when encoding to a string.
185+ * Default value is `0`.
186+ */
129187 public var spacesBeforeSeparator: Int = from.spacesBeforeSeparator
188+
189+ /* *
190+ * A number of spaces to be inserted after the [keyValueSeparator] when encoding to a string.
191+ * Default value is `0`.
192+ */
130193 public var spacesAfterSeparator: Int = from.spacesAfterSeparator
194+
195+ /* *
196+ * A [SerializersModule] to be used for encoding and decoding.
197+ * Default value is [EmptySerializersModule].
198+ */
131199 public var module: SerializersModule = from.serializersModule
132200
133201 internal fun build (): PropertiesConf {
0 commit comments