Skip to content

No _valueDeserializer assigned when @JacksonXmlProperty.localName and field name have the same name. #274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
billoneil opened this issue Dec 5, 2017 · 3 comments
Milestone

Comments

@billoneil
Copy link

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.

@cowtowncoder
Copy link
Member

Hmmh. That is unfortunate. I assume further 2.8 versions have same problem? (2.8.9 - 2.8.11)

Aside from this, would it be possible to try out 2.9? (I'll do that when I get a chance)

@cowtowncoder
Copy link
Member

Also: could it be #273 might be related?

cowtowncoder added a commit that referenced this issue May 21, 2018
@cowtowncoder
Copy link
Member

I can not reproduce this with 2.9 (pre-2.9.6). May be reopened with failing test case.
(test class Issue274PropertyNameTest slightly simplified -- could be something I did, but I can't see any reason).

@cowtowncoder cowtowncoder added this to the 2.9.5 milestone May 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants