Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encodeToString produces wrong indentation for case when there are nested List among the tree #254

Open
vlsi opened this issue Jan 16, 2024 · 2 comments

Comments

@vlsi
Copy link
Contributor

vlsi commented Jan 16, 2024

class NestedListsTest {
    @Serializable
    data class Wrapper(
        val elements: List<Element>
    )

    @Serializable
    data class Element(
        val name: String,
        val subElements: List<SubElement>
    )

    @Serializable
    data class SubElement(
        val name: String,
        val description: String,
    )

    @Test
    fun test() {
        val data = Wrapper(
            elements = listOf(
                Element(
                    name = "element 1",
                    subElements = listOf(
                        SubElement("1.1", "d1.1"),
                        SubElement("1.2", "d1.2"),
                    )
                ),
            )
        )
        val serialized = Toml.encodeToString(data)

        Assert.assertEquals(
            serialized,
            """
            [[elements]]
                name = "element 1"

                [[elements.subElements]]
                    name = "1.1"
                    description = "d1.1"

                [[elements.subElements]]
                    name = "1.2"
                    description = "d1.2"
            """.trimIndent()
        )

        val deserialized = Toml.decodeFromString<Wrapper>(serialized)

        Assert.assertEquals(data, deserialized)
    }
}

com.akuleshov7:ktoml-core:0.5.1 yields

[[elements]]
    name = "element 1"

    [[elements.subElements]]
        name = "1.1"
        description = "d1.1"

[[elements.subElements]]
        name = "1.2"
        description = "d1.2"

The generated TOML does not parse. It would be nice if the error message included the problematic field name or something like that. Currently the error message provides little to no clue on why the parsing went wrong:

com.akuleshov7.ktoml.exceptions.MissingRequiredPropertyException: Invalid number of key-value arguments provided in the input for deserialization. Missing required property <0> from class <kotlin.collections.ArrayList> in the input. (In your deserialization class you have declared this field, but it is missing in the input)
	at app//com.akuleshov7.ktoml.decoders.TomlMainDecoder.checkMissingRequiredProperties(TomlMainDecoder.kt:200)
	at app//com.akuleshov7.ktoml.decoders.TomlMainDecoder.iterateOverTomlStructure(TomlMainDecoder.kt:258)
	at app//com.akuleshov7.ktoml.decoders.TomlMainDecoder.beginStructure(TomlMainDecoder.kt:220)
	at app//kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:29)
	at app//kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
	at app//kotlinx.serialization.encoding.Decoder$DefaultImpls.decodeSerializableValue(Decoding.kt:257)
	at app//kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:16)
	at app//com.akuleshov7.ktoml.decoders.TomlAbstractDecoder.decodeSerializableValue(TomlAbstractDecoder.kt:96)
	at app//kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:43)
	at app//kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableElement(AbstractDecoder.kt:70)
	at app//com.example.NestedListsTest$Wrapper$$serializer.deserialize(TomlTest.kt:11)
	at app//com.example.NestedListsTest$Wrapper$$serializer.deserialize(TomlTest.kt:11)
	at app//kotlinx.serialization.encoding.Decoder$DefaultImpls.decodeSerializableValue(Decoding.kt:257)
	at app//kotlinx.serialization.encoding.AbstractDecoder.decodeSerializableValue(AbstractDecoder.kt:16)
	at app//com.akuleshov7.ktoml.decoders.TomlAbstractDecoder.decodeSerializableValue(TomlAbstractDecoder.kt:96)
	at app//com.akuleshov7.ktoml.decoders.TomlMainDecoder$Companion.decode(TomlMainDecoder.kt:293)
	at app//com.akuleshov7.ktoml.Toml.decodeFromString(Toml.kt:47)
	at app//com.example.NestedListsTest.test(TomlTest.kt:66)
@vlsi
Copy link
Contributor Author

vlsi commented Jan 16, 2024

In case you wonder,

    @Serializable
    data class Wrapper(
        val elements: List<Element>
    )

    @Serializable
    data class Element(
        val name: String,
        val subElements: List<SubElement>
    )

    @Serializable
    data class SubElement(
        val name: String,
        val description: String,
        val subSubElements: List<SubSubElement>,
    )

    @Serializable
    data class SubSubElement(
        val name: String,
        val description: String,
    )

with

val data = Wrapper(
    elements = listOf(
        Element(
            name = "element 1",
            subElements = listOf(
                SubElement(
                    "1.1", "d1.1",
                    subSubElements =
                    listOf(
                        SubSubElement("1.1.1", "d1.1.1"),
                        SubSubElement("1.1.2", "d1.1.2")
                    )
                ),
                SubElement(
                    "1.2", "d1.2",
                    subSubElements =
                    listOf(
                        SubSubElement("1.2.1", "d1.2.1"),
                        SubSubElement("1.2.2", "d1.2.2"),
                    )
                ),
            )
        ),
        Element(
            name = "element 2",
            subElements = listOf(
                SubElement(
                    "2.1", "d2.1",
                    subSubElements =
                    listOf(
                        SubSubElement("2.1.1", "d2.1.1"),
                        SubSubElement("2.1.2", "d2.1.2"),
                    )
                ),
                SubElement(
                    "2.2", "d2.2",
                    subSubElements =
                    listOf(
                        SubSubElement("2.2.1", "d2.2.1"),
                        SubSubElement("2.2.2", "d2.2.2"),
                    )
                ),
            )
        ),
    )
)

yields

[[elements]]
    name = "element 1"

    [[elements.subElements]]
        name = "1.1"
        description = "d1.1"

        [[elements.subElements.subSubElements]]
            name = "1.1.1"
            description = "d1.1.1"

[[elements.subElements.subSubElements]]
            name = "1.1.2"
            description = "d1.1.2"

[[elements.subElements]]
        name = "1.2"
        description = "d1.2"

        [[elements.subElements.subSubElements]]
            name = "1.2.1"
            description = "d1.2.1"

[[elements.subElements.subSubElements]]
            name = "1.2.2"
            description = "d1.2.2"

[[elements]]
    name = "element 2"

    [[elements.subElements]]
        name = "2.1"
        description = "d2.1"

        [[elements.subElements.subSubElements]]
            name = "2.1.1"
            description = "d2.1.1"

[[elements.subElements.subSubElements]]
            name = "2.1.2"
            description = "d2.1.2"

[[elements.subElements]]
        name = "2.2"
        description = "d2.2"

        [[elements.subElements.subSubElements]]
            name = "2.2.1"
            description = "d2.2.1"

[[elements.subElements.subSubElements]]
            name = "2.2.2"
            description = "d2.2.2"

@orchestr7
Copy link
Owner

Decoding fails due to ArrayOfTables https://toml.io/en/v1.0.0#array-of-tables . It has mostly a zero support in our lib.

But spacing should be fixed, definitely

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants