Search code examples
jackson-dataformat-xml

Jackson xml (de)serialization with custom boolean format


I have xml file:

<?xml version="1.0" encoding="UTF-8"?>
<ADDRESSOBJECTS>
    <OBJECT ID="1802267" NAME="SomeName" ISACTIVE="1" />
</ADDRESSOBJECTS>

and correponding classes in kotlin:

@JacksonXmlRootElement(localName = "ADDRESSOBJECTS")
class AddressingObjectCollection {
    @JacksonXmlProperty(localName = "OBJECT")
    @JacksonXmlElementWrapper(useWrapping = false)
    open lateinit var objects: List<AddressingObject>
}

and

class AddressingObject : Serializable {
    @JacksonXmlProperty(isAttribute = true, localName = "ID")
    open var id: Long = 0

    @JacksonXmlProperty(isAttribute = true, localName = "NAME")
    open lateinit var name: String

    @JacksonXmlProperty(isAttribute = true, localName = "ISACTIVE")
    open var isActive: Boolean = false
}

when I try to deserialize I get error:

val deserialized = mapper.readValue(File(file).readText(), AddressingObjectCollection::class.java)

error:

Cannot deserialize value of type `boolean` from String "1": only "true"/"True"/"TRUE" or "false"/"False"/"FALSE" recognized

How to tell jackson to (de)serialize this format properly?


Solution

  • For this purpose I use Json attributes:

    @JsonProperty("ISACTIVE")
    @JacksonXmlProperty(isAttribute = true, localName = "ISACTIVE")
    @JsonDeserialize(using = CustomBooleanDeserializer::class)
    open var isActive: Boolean = false
    

    And CustomBooleanDeserializer:

    class CustomBooleanDeserializer : JsonDeserializer<Boolean>() {
        override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Boolean {
            if (p?.currentTokenId() == JsonTokenId.ID_STRING){
                var text = p.text
    
                if (text == "1") return true
            }
    
            return false;
        }
    }
    

    It works for me.