title: How to perform a custom JSON deserialization with Jackson that respects a custom annotation?
body: <p>I am trying to deserialize JSON into a custom POJO that I am not able to modify.  That POJO has annotations from a different custom internal serialization framework that I'm not able to use.  How can I create a custom deserializer that will respect these annotations?</p>
  <p>Here is an example POJO:</p>
  <pre class="lang-java prettyprint-override"><code>public class ExampleClass {
      @Property(name = &quot;id&quot;)
      public String id;
  
      @Property(name = &quot;time_windows&quot;)
      @NotNull
      public List&lt;TimeWindow&gt; timeWindows = new ArrayList&lt;&gt;();
  
      public static class TimeWindow {
          @Property(name = &quot;start&quot;)
          public Long start;
  
          @Property(name = &quot;end&quot;)
          public Long end;
      }
  }
  </code></pre>
  <p>So in this case, the deserializer would look for fields in the JSON that correspond to the <code>Property</code> annotations, and use the value in that annotation to decide what field to grab.  If a property <em>doesn't</em> have the <code>Property</code> annotation, it should be ignored.</p>
  <p>I have been going through the Jackson docs but haven't been able to find exactly what I need.  Is this a place where an <code>AnnotationIntrospector</code> would be useful?  Or possibly a <code>ContextualDeserializer</code>?</p>
  <p>Any pointers in the right direction would be greatly appreciated!</p>
  <hr />
  <p><strong>Update: I tried implementing the advice in the comments, but without success.</strong></p>
  <p>Here is my initial implementation of the introspector:</p>
  <pre class="lang-kotlin prettyprint-override"><code>class CustomAnnotationInspector : JacksonAnnotationIntrospector () {
      override fun hasIgnoreMarker(m: AnnotatedMember?): Boolean {
          val property = m?.getAnnotation(Property::class.java)
          return property == null
      }
  
      override fun findNameForDeserialization(a: Annotated?): PropertyName {
          val property = a?.getAnnotation(Property::class.java)
          return if (property == null) {
              super.findNameForDeserialization(a)
          } else {
              PropertyName(property.name)
          }
      }
  }
  </code></pre>
  <p>And here is where I actually use it:</p>
  <pre class="lang-kotlin prettyprint-override"><code>// Create an empty instance of the request object.
  val paramInstance = nonPathParams?.type?.getDeclaredConstructor()?.newInstance()
  
  // Create new object mapper that will write values from
  // JSON into the empty object.
  val mapper = ObjectMapper()
  
  // Tells the mapper to respect custom annotations.
  mapper.setAnnotationIntrospector(CustomAnnotationInspector())
  
  // Write the contents of the request body into the StringWriter
  // (this is required for the mapper.writeValue method
  val sw = StringWriter()
  sw.write(context.bodyAsString)
  
  // Deserialize the contents of the StringWriter
  // into the empty POJO.
  mapper.writeValue(sw, paramInstance)
  </code></pre>
  <p>Unfortunately it seems that <code>findNameForDeserialization</code> is never called, and none of the JSON values are written into <code>paramInstance</code>.  Can anybody spot where I'm going wrong?</p>
  <p>Thank you!</p>
  <hr />
  <p><strong>Update 2: I changed the code slightly, I'm now able to identify the property names but Jackson is failing to create an instance of the object.</strong></p>
  <p>Here's my new code:</p>
  <pre class="lang-kotlin prettyprint-override"><code>val mapper = ObjectMapper()
  
  // Tells the mapper to respect CoreNg annotations.
  val introspector = CustomAnnotationInspector()
  mapper.setAnnotationIntrospector(introspector)
  
  val paramInstance = mapper.readValue(context.bodyAsString,nonPathParams?.type)
  </code></pre>
  <p>My breakpoints in the custom annotation introspector are getting hit.  But I'm getting the following exception:</p>
  <pre><code>com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `app.employee.api.employee.BOUpsertEmployeeRequest` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
  </code></pre>
  <p>Here is the POJO I'm trying to deserialize:</p>
  <pre class="lang-java prettyprint-override"><code>public class BOUpsertEmployeeRequest {
      public BOUpsertEmployeeRequest () { }
  
      @NotNull
      @Property(name = &quot;xref_code&quot;)
      public String xrefCode;
  
      @Property(name = &quot;first_name&quot;)
      public String firstName;
  
      @Property(name = &quot;last_name&quot;)
      public String lastName;
  
      @Property(name = &quot;email_address&quot;)
      public String emailAddress;
  
      @Property(name = &quot;phone&quot;)
      public String phone;
  
      @Property(name = &quot;address&quot;)
      public List&lt;String&gt; address;
  
      @Property(name = &quot;employment_status&quot;)
      public String employmentStatus;
  
      @Property(name = &quot;pay_type&quot;)
      public String payType;
  
      @Property(name = &quot;position&quot;)
      public String position;
  
      @Property(name = &quot;skills&quot;)
      public List&lt;String&gt; skills;
  
      @Property(name = &quot;gender&quot;)
      public String gender;
  }
  </code></pre>
  <p>As far as I can tell it has a default constructor.  Anybody have any idea what the problem is?</p>
  <p>Thank you!</p>