https://kotlinlang.org logo
#jackson-kotlin
Title
# jackson-kotlin
m

martmists

10/31/2021, 6:23 PM
How do I read XML lists properly from kotlin? Classes:
Copy code
enum class Language {
    AmericanEnglish,
    BritishEnglish,
    Japanese,
    French,
    German,
    LatinAmericanSpanish,
    Spanish,
    Italian,
    Dutch,
    CanadianFrench,
    Russian,
    Korean,
    TraditionalChinese,
    SimplifiedChinese,
    Unknown
}

data class TitleName(
    val language: Language,
    val name: String,
    val publisher: String
)

data class NACP(
    val title: List<TitleName>,
    // TODO: Add more
)
XML (simplified):
Copy code
<?xml version="1.0" encoding="utf-8"?>
<Application>
    <Title>
        <Language>AmericanEnglish</Language>
        <Name>Mario Party Superstars</Name>
        <Publisher>Nintendo</Publisher>
    </Title>
    <Title>
        <Language>BritishEnglish</Language>
        <Name>Mario Party Superstars</Name>
        <Publisher>Nintendo</Publisher>
    </Title>
    <Title>
        <Language>Japanese</Language>
        <Name> ̄デ ̄テᆰ ̄ツᆰ ̄テム ̄テᄐ ̄テニ ̄ツᆪ  ̄ツᄍ ̄テᄐ ̄テム ̄テᄐ ̄ツᄍ ̄ツ﾿ ̄テᄐ ̄ツᄎ</Name>
        <Publisher>Nintendo</Publisher>
    </Title>
</Application>
Code:
Copy code
val parser = XmlMapper.builder()
    .addModule(
        KotlinModule.Builder()
            // Defaults
            .withReflectionCacheSize(512)
            .configure(KotlinFeature.NullToEmptyCollection, false)
            .configure(KotlinFeature.NullToEmptyMap, false)
            .configure(KotlinFeature.NullIsSameAsDefault, false)
            .configure(KotlinFeature.SingletonSupport, false)
            .configure(KotlinFeature.StrictNullChecks, false)
            .build()
    )
    // Defaults
    .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false)
    .configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false)
    .build()

parser.readValue<NACP>(xml)
// => com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `TitleName` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('AmericanEnglish')
d

dinomite

10/31/2021, 7:28 PM
Hmm, I don’t ever use XML, but it looks to me like perhaps you need that
val
in
NACP
to be named
application
(you could also add
@JsonProperty("application")
)
To see what the parser is expecting, build an object in memory (i.e.
val nacp = NACP(listOf(TitleName(…)))
) and then serialize it using the object mapper:
parser.writeValueAsString(nacp)
m

martmists

10/31/2021, 7:50 PM
The parser is likely expecting
Contents
to only appear once, with a bunch of elements like
item
which have those blocks inside it, but this bug should have been fixed about 8 years ago
yup:
Copy code
<?xml version="1.0" encoding="UTF-8"?>
<NACP>
   <title>
      <title>
         <language>AmericanEnglish</language>
         <name>English Name</name>
         <publisher>Publisher</publisher>
      </title>
      <title>
         <language>BritishEnglish</language>
         <name>British English Name</name>
         <publisher>Publisher</publisher>
      </title>
      <title>
         <language>Dutch</language>
         <name>Dutch Name</name>
         <publisher>Publisher</publisher>
      </title>
   </title>
</NACP>
d

dinomite

11/01/2021, 1:05 PM
Hmm, I’d be surprised for such a glaring bug to persist in Jackson, perhaps it’s just a conceptual misunderstanding?
In JSON, I’d expect your object to look like:
Copy code
{
    "title": [
        {"language": "AmericanEnglish", "name": "Mario Party Superstars", "publisher": "Nintendo"},
        …
    ]
}
So what you have above (https://kotlinlang.slack.com/archives/C0BLHCSHZ/p1635709970004500?thread_ts=1635704610.002700&amp;cid=C0BLHCSHZ) makes sense to me, because XML doesn’t have a list type
16 Views