@@ -22,24 +22,10 @@ Container & TestElement - [data.kt](src/main/kotlin/net/devrieze/serialization/e
2222data class Container (val data : List <TestElement >)
2323
2424@Serializable
25- data class TestElement (val id : Int , val attr : Int , @XmlElement( true ) val data : String )
25+ data class TestElement (val id : Int , val attr : Int , @XmlElement val data : String )
2626```
2727
28- There are 2 example serializers. One works in 0.80.0 and 0.80.1 and the other one will work on the master/dev branches
29- only. Almost all code is shared though.
30-
31- [ CompatContainerSerializer] ( src/main/kotlin/net/devrieze/serialization/examples/dynamictagnames/CompatContainerSerializer.kt )
32- ``` kotlin
33- /* *
34- * The compatible serializer doesn't have access to state to determine a proper delegate format. This
35- * implementation uses the default format instance. It is perfectly valid however to create a custom
36- * instance (for example providing a SerialModule) here and return that from both delegate methods
37- */
38- object CompatContainerSerializer: CommonContainerSerializer() {
39- override fun delegateFormat (decoder : Decoder ) = XML .defaultInstance
40- override fun delegateFormat (encoder : Encoder ) = XML .defaultInstance
41- }
42- ```
28+ The following serializer only works in versions after 0.80.1.
4329
4430[ ContainerSerializer] ( src/main/kotlin/net/devrieze/serialization/examples/dynamictagnames/ContainerSerializer.kt )
4531``` kotlin
@@ -194,6 +180,7 @@ internal class DynamicTagReader(reader: XmlReader, descriptor: XmlDescriptor) :
194180 * Store the name of the id attribute that is synthetically generated. This property is initialised
195181 * this way to allow for name remapping in the format policy.
196182 */
183+ @OptIn(ExperimentalSerializationApi ::class )
197184 private val idAttrName = (0 until descriptor.elementsCount)
198185 .first { descriptor.serialDescriptor.getElementName(it) == " id" }
199186 .let { descriptor.getElementDescriptor(it) }
@@ -283,18 +270,22 @@ internal class DynamicTagReader(reader: XmlReader, descriptor: XmlDescriptor) :
283270 * When we are at relative depth 0 we return the synthetic name rather than the original.
284271 */
285272 override val namespaceURI: String
286- get() = when (filterDepth) {
287- 0 -> elementName.namespaceURI
288- else -> super .namespaceURI
273+ get() {
274+ return when (filterDepth) {
275+ 0 -> elementName.namespaceURI
276+ else -> super .namespaceURI
277+ }
289278 }
290279
291280 /* *
292281 * When we are at relative depth 0 we return the synthetic name rather than the original.
293282 */
294283 override val localName: String
295- get() = when (filterDepth) {
296- 0 -> elementName.localPart
297- else -> super .localName
284+ get() {
285+ return when (filterDepth) {
286+ 0 -> elementName.localPart
287+ else -> super .localName
288+ }
298289 }
299290
300291 /* *
@@ -327,6 +318,7 @@ internal class DynamicTagWriter(private val writer: XmlWriter, descriptor: XmlDe
327318 */
328319 get() = writer.depth - initDepth
329320
321+ @OptIn(ExperimentalSerializationApi ::class )
330322 private val idAttrName = (0 until descriptor.elementsCount)
331323 .first { descriptor.serialDescriptor.getElementName(it) == " id" }
332324 .let { descriptor.getElementDescriptor(it) }
@@ -338,7 +330,7 @@ internal class DynamicTagWriter(private val writer: XmlWriter, descriptor: XmlDe
338330 */
339331 override fun startTag (namespace : String? , localName : String , prefix : String? ) {
340332 when (filterDepth) {
341- 0 -> super .startTag(" " , " Test_$idValue " , " " )
333+ 0 -> super .startTag(" " , " Test_$idValue " , " " )
342334 else -> super .startTag(namespace, localName, prefix)
343335 }
344336 }
@@ -351,7 +343,8 @@ internal class DynamicTagWriter(private val writer: XmlWriter, descriptor: XmlDe
351343 filterDepth == 1 &&
352344 (namespace ? : " " ) == idAttrName.namespaceURI &&
353345 name == idAttrName.localPart
354- -> Unit
346+ -> Unit
347+
355348 else -> super .attribute(namespace, name, prefix, value)
356349 }
357350
@@ -362,82 +355,9 @@ internal class DynamicTagWriter(private val writer: XmlWriter, descriptor: XmlDe
362355 */
363356 override fun endTag (namespace : String? , localName : String , prefix : String? ) {
364357 when (filterDepth) {
365- 1 -> super .endTag(" " , " Test_$idValue " , " " )
358+ 1 -> super .endTag(" " , " Test_$idValue " , " " )
366359 else -> super .endTag(namespace, localName, prefix)
367360 }
368361 }
369362}
370363```
371-
372-
373- ## Example usage
374- [ main.kt] ( src/main/kotlin/net/devrieze/serialization/examples/dynamictagnames/main.kt )
375- ``` kotlin
376- /* *
377- * This example shows how a custom serializer together with a filter can be used to support non-xml xml documents
378- * where tag names are dynamic/unique. This example is a solution to the question in #41.
379- *
380- * There are 2 versions, one is the CompatContainerSerializer. This version works on 0.80.0 and 0.80.1 but has
381- * limitations in that it cannot inherit configuration or serializerModules. The improved version uses new properties
382- * in the XML.XmlInput and XML.XmlOutput interfaces that allow new xml serializers to be created based on the
383- * configuration of the encoder/decoder.
384- */
385- fun main () {
386- /*
387- * Some test data that is used for both versions of the serializer.
388- */
389- val testElements = listOf (
390- TestElement (123 , 42 , " someData" ),
391- TestElement (456 , 71 , " moreData" )
392- )
393-
394- // Execute the example code for the compatible serializer
395- println (" # Compatible" )
396- compat(testElements)
397-
398- // Execute the example code for the improved serializer
399- println ()
400- println (" # Improved version" )
401- newExample(testElements)
402- }
403-
404- private fun compat (testElements : List <TestElement >) {
405- val data = Container (testElements)
406-
407- // Instead of using the serializer for the type we use the custom one. In normal cases there would only be one
408- // serializer
409- val serializer = CompatContainerSerializer
410-
411- /*
412- * Set an indent here to show that it is not effective (as the serialization of the child does not have access to
413- * the configuration).
414- */
415- val xml = XML { indent = 2 }
416-
417- // Encode and print the output of serialization
418- val string = xml.encodeToString(serializer, data)
419- println (" StringEncodingCompat:\n ${string.prependIndent(" " )} " )
420-
421- // Parse and print the result of deserialization
422- val deserializedData = xml.decodeFromString(serializer, string)
423- println (" Deserialized container:\n $deserializedData " )
424- }
425-
426- /* * This example works with master, but not with the released version. */
427- private fun newExample (testElements : List <TestElement >) {
428- val data = Container (testElements)
429- val serializer = serializer<Container >() // use the default serializer
430-
431- // Create the configuration for (de)serialization
432- val xml = XML { indent = 2 }
433-
434- // Encode and print the output of serialization
435- val string = xml.encodeToString(serializer, data)
436- println (" StringEncodingCompat:\n ${string.prependIndent(" " )} " )
437-
438- // Parse and print the result of deserialization
439- val deserializedData = xml.decodeFromString(serializer, string)
440- println (" Deserialized container:\n $deserializedData " )
441-
442- }
443- ```
0 commit comments