XML Dátumkezelés

XML szerializálás (marshalling) vagy deszerilizálás (unmarshalling) során a dátumok egyedi formátumának kezeléséhez szükséges pár plusz lépést megtennünk.

Az adatmodellben annotálnunk kell a dátum mezőket a @XmlJavaTypeAdapter annotációval, amelynek értéke egy XmlAdapter implementáció lesz.

@field:XmlJavaTypeAdapter(ShortDateAdapter::class)
var createdDate: LocalDate? = null,

Ehhez nyilvánvalóan létre kell hoznunk a ShortDateAdapter osztályt is.

class ShortDateAdapter(
    dateFormat: String = "yyyy-MM-dd"
) : XmlAdapter<String, LocalDate>() {

    private val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat)

    override fun unmarshal(xml: String): LocalDate? {
        val parse = LocalDate.parse(xml, dateFormatter)
        return parse
    }

    override fun marshal(date: LocalDate): String {
        return dateFormatter.format(date)
    }
}

Ezzel a megoldással az alkalmazásunk képes lesz a megfelelő formátumban kezelni a dátumokat az XML műveletek során.

Ahogyan látható, itt a dátum formátuma egy fix, alapértelmezett értéket kapott. Ha ez az érték nem egy osztály-beli fix érték, hanem konstruktorban adjuk át, akkor felül is tudjuk írni. Ha konstruktorban adjuk át a formátumot, akkor fordításkor hibát kaphatunk, ugyanis az osztályunk nem rendelkezik default konstruktorral, amit az @XmlJavaTypeAdapter annotáció használhatna.

Ennek megoldására érdemes lehet létrehozni egy "központi" MarshallerFactory-t, aminek át tudjuk adni azokat az adaptereket, amiket használni akarunk:

class MarshallerFactory {
	inline fun <reified T> createMarshaller(adapters: List<XmlAdapter<String, *>>? = null): Marshaller =
		JAXBContext.newInstance(T::class.java).createMarshaller().apply {
			setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)
			adapters?.forEach { setAdapter(it) }
		}
}

Bekötéshez:

private val customMarshaller = marshallerFactory.createMarshaller<MyCustomDataModel>(listOf(shortDateAdapter))

A pozitívum, hogy ezzel a kis plusz munkával a dátumformátumokat egyszerűen kivezethetjük konfigurációba is, pl. application.yml fájlba.