Description
I'm not sure exactly how this was tracked down but our XML serializer started breaking between version 2.8.7
and 2.8.8
with a
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: No _valueDeserializer assigned
at [Source: (StringReader); line: 4, column: 32] (through reference chain: JacksonTest$RootObject["Event"]->JacksonTest$Event["EventId"])
It appears the actual change was in jackson-databind-2.8.7-2.8.8 since there are no notable changes in jackson-dataformat-xml-2.8.7-2.8.8 but seems related to the XML annotations. Here is the best example I could come up with to reproduce.
public class JacksonTest {
private static final String XML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<dataroot xmlns:od=\"urn:schemas-microsoft-com:officedata\" generated=\"2017-06-07T10:11:20\">\n" +
" <Event>\n" +
" <EventId>34906566143035</EventId>\n" +
" </Event>\n" +
"</dataroot>";
static class Event {
@JacksonXmlProperty(localName = "EventId")
private String EventId;
public String getEventId() {
return EventId;
}
public void setEventId(String eventId) {
this.EventId = eventId;
}
}
@JacksonXmlRootElement(localName = "dataroot")
static class RootObject {
@JacksonXmlProperty(localName = "Event")
Event event;
@JacksonXmlProperty(localName = "generated")
String generated;
}
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
JacksonXmlModule module = new JacksonXmlModule();
XmlFactory factory = new XmlFactory();
XMLOutputFactory outputFactory = new WstxOutputFactory();
//fix default namespace issue
outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", true);
//Woodstox is the recommended Stax XML API implementation by fasterXml/Jackson
factory.setXMLOutputFactory(outputFactory);
factory.setXMLInputFactory(new WstxInputFactory());
XmlMapper xm = new XmlMapper(factory, module);
// serialization features
xm.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
xm.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// deserialization features
xm.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
//this is for deserialization only and means we don't need to camelCase xml property names
xm.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
// enable JAXB as primary introspector
AnnotationIntrospector jaxbIntrospector = new JaxbAnnotationIntrospector(xm.getTypeFactory());
AnnotationIntrospector jacksonXmlIntrospector = new JacksonXmlAnnotationIntrospector();
AnnotationIntrospector pair = new AnnotationIntrospectorPair(jaxbIntrospector, jacksonXmlIntrospector);
xm.setAnnotationIntrospector(pair);
RootObject obj = xm.readValue(XML, new TypeReference<RootObject>() {});
}
}
However, commenting out the XML annotation will work.
static class Event {
//@JacksonXmlProperty(localName = "EventId")
private String EventId;
public String getEventId() {
return EventId;
}
public void setEventId(String eventId) {
this.EventId = eventId;
}
}
Removing the setter and keeping the annotation will also work.
static class Event {
@JacksonXmlProperty(localName = "EventId")
private String EventId;
public String getEventId() {
return EventId;
}
}
Fixing the case of the field will also work.
static class Event {
@JacksonXmlProperty(localName = "EventId")
private String eventId;
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
}
And finally commenting out MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES seems to work.
//xm.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
This issue only appears to happen when the field name and annotation names match AND there is a setter. From version 2.8.8+ this throws an exception. I can fix this on our end with any of the mentioned fixes just thought I would mention it.