jackson-databind: Failure to find creator property with Lombok and an unwrapping mixin involved

The following test case:

public class JacksonTest {

    @Test
    public void testname() throws Exception {

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new ParameterNamesModule());
        mapper.addMixIn(Foo.class, FooMixin.class);

        mapper.readValue("{ \"foo\" : \"something\", \"bar\" : \"something\" }", Foo.class);
    }

    @AllArgsConstructor
    static class Foo {

        String foo, bar;
        Nested nested;

        public Nested getNested() {
            return nested;
        }
    }

    @AllArgsConstructor
    static class Nested {}

    interface FooMixin {

        @JsonUnwrapped
        Nested getNested();
    }
}

results in the following exception:

com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'nested' (in class com.example.JacksonTest$Foo)
 at [Source: { "foo" : "something", "bar" : "something" }; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:255)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:992)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:541)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:228)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)

The following things make it work and I kind of have a hard time understanding why 😃:

  • Removing @JsonUnwrapped from the mixin
  • Removing getNested() from the mixin entirely
  • Not registering the mixin
  • Adding suppressConstructorProperties = true to @AllArgsConstructor on Foo.

So it looks like that the ā€œoverrideā€ of the accessor in the mixin has a higher priority than the constructor that’s generated by default Lombok. However, tricking Lombok into not adding the explicit constructor argument annotations seems to resolve the issue, too.

The error appears on 2.7.4, 2.6.5 works fine. Originally I thought I run into something related to #1122, but that one was resolved in 2.7.4.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 8
  • Comments: 21 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Our team ran in to this issue today in a JDK8 project when upgrading from Spring Boot 1.5.1 to 1.5.2 (tons of dependency updates). After the upgrade, our controllers could not deserialize nested Lombok-annotated objects until a child object’s @AllArgsConstructor annotation was updated with suppressConstructorProperties = true.

We ultimately created a lombok.config file in our project with this setting to fix the problem globally:

lombok.anyConstructor.suppressConstructorProperties = true

It’s been hard for us to work through the above conversation and links to understand the context and the underlying issue. Is this an appropriate fix for the problem? Would there be any value in us creating an example project to share demonstrating the issue?

The example presented in my original post works on current Lombok generations as 1.16.20 changed its behavior to now not add the @ConstructorProperties annotation by default anymore. However, if I configure it to add the annotation again (by setting lombok.anyConstructor.addConstructorProperties = true in lombok.config) the exception still appears.

In fact, this ins’t even a Lombok issue at all. I’ve just removed Lombok and added @ConstructorProperties manually and the error appears:

public class JacksonTest {

	@Test
	public void testname() throws Exception {

		ObjectMapper mapper = new ObjectMapper();
		mapper.registerModule(new ParameterNamesModule());
		mapper.addMixIn(Foo.class, FooMixin.class);

		mapper.readValue("{ \"foo\" : \"something\", \"bar\" : \"something\" }", Foo.class);
	}

	static class Foo {

		String foo, bar;
		Nested nested;

		@ConstructorProperties({ "foo", "bar", "nested" })
		public Foo(String foo, String bar, Nested nested) {}

		public Nested getNested() {
			return nested;
		}
	}

	@AllArgsConstructor
	static class Nested {}

	interface FooMixin {

		@JsonUnwrapped
		Nested getNested();
	}
}

Removing @ConstructorProperties makes the test succeed. I’m using Jackson 2.9.6 these days. Stack trace is:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot define Creator property "nested" as `@JsonUnwrapped`: combination not yet supported
 at [Source: (String)"{ "foo" : "something", "bar" : "something" }"; line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase._findPropertyUnwrapper(BeanDeserializerBase.java:836)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:494)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4190)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4009)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
	at JacksonTest.testname(JacksonTest.java:20)
	…