pdvrieze / xmlutil

XML Serialization library for Kotlin
https://pdvrieze.github.io/xmlutil/
Apache License 2.0
363 stars 30 forks source link

Include failed content when decoding #197

Open hfhbd opened 4 months ago

hfhbd commented 4 months ago

Like kotlinx.serialization.json, it would be helpful to include the content when decoding, ideally the attribute/element (including its namespace) that failed.

Given class:

@Serializable
data class A(val a: String, val c: Int)

Using json Json.decodeFromString(A.serializer(), """{"a": "b", "d": 42}"""):

kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 13: Encountered an unknown key 'd' at path: $.a
Use 'ignoreUnknownKeys = true' in 'Json {}' builder to ignore unknown keys.
JSON input: {"a":  "b", "d":  42}

Using xml XML.decodeFromString(A.serializer(), """<A a="asd" d="asfd"/>"""):

nl.adaptivity.xmlutil.serialization.UnknownXmlFieldException: Could not find a field for name (ATest.A) A/d (Attribute)
  candidates: a (Attribute), c (Attribute) at position Line number = 1
Column number = 22
System Id = null
Public Id = null
Location Uri= null
CharacterOffset = 21
pdvrieze commented 4 months ago

I may add support for this, but it can't be default behaviour in all cases as it requires having access to the original string (you don't want to do this on streaming). Note that it already provides line/character number as well as the context (type, parentTagName/unknownName) and the expected names (and what type they are). It does provide namespaces, but hides empty namespaces to keep the output compact.

hfhbd commented 4 months ago

Yes, I don't expect the full input string, but the failed element only, which is already needed by the parser/decoder, isn't it? With large inputs, the full string is also not really helpful too.

AFAIK the json deserializer also only contains the current item (and the next x characters).

pdvrieze commented 4 months ago

@hfhbd The problem is that for element (rather than attribute) children the "current" element is the child, rather than the container/parent. And the place in the code where this triggers is used to resolve both tag and attribute names.