Skip to content

Commit 3c73391

Browse files
committed
Update the dynamic tag name example.
1 parent 0643ecd commit 3c73391

File tree

2 files changed

+19
-99
lines changed

2 files changed

+19
-99
lines changed

examples/DYNAMIC_TAG_NAMES.md

Lines changed: 18 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,10 @@ Container & TestElement - [data.kt](src/main/kotlin/net/devrieze/serialization/e
2222
data 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-
```

examples/src/main/kotlin/net/devrieze/serialization/examples/dynamictagnames/data.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ import nl.adaptivity.xmlutil.serialization.XmlElement
3131
data class Container(val data: List<TestElement>)
3232

3333
@Serializable
34-
data class TestElement(val id: Int, val attr: Int, @XmlElement(true) val data: String)
34+
data class TestElement(val id: Int, val attr: Int, @XmlElement val data: String)

0 commit comments

Comments
 (0)