title: deserialize generic class using jackson-module-kotlin
body: <p>I'm trying to use the jackson-kotlin integration. Mostly it works nice but I'm having trouble with deserializing generic types. I tried to adapt the answer to this question: <a href="https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class">Jackson - Deserialize using generic class</a></p>
  
  <pre><code>    // create an object mapper
      val jsonFactory = JsonFactory()
      jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
      jsonFactory.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
  
      val objectMapper = ObjectMapper(jsonFactory)
      objectMapper.findAndRegisterModules()
      objectMapper.propertyNamingStrategy = PropertyNamingStrategy.SnakeCaseStrategy()
          objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
  
      // simple generic type
      data class Inner(val meaningOfLife: Int)
      data class Outer&lt;T&gt;(val inner: T)
  
      val outer = Outer(Inner(42))
  
      val serialized = objectMapper.stringify(outer, true)
      println(serialized)
  
      // deserializing does not work using:
      // https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
      val parsed = objectMapper.readValue&lt;Outer&lt;Inner&gt;&gt;(serialized, objectMapper.typeFactory.constructParametricType(Outer::class.java,Inner::class.java))
  </code></pre>
  
  <p>This throws an exception:</p>
  
  <pre><code>com.fasterxml.jackson.databind.JsonMappingException: Cannot deserialize Class io.inbot.common.ObjectMapperTest$should handle generics$Outer (of type local/anonymous) as a Bean
   at [Source: (String)"{
    "inner" : {
      "meaning_of_life" : 42
    }
  }"; line: 1, column: 1]
  
      at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:306)
      at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:268)
      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:3042)
      at io.inbot.common.ObjectMapperTest.should handle generics(ObjectMapperTest.kt:22)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
      at org.testng.internal.Invoker.invokeMethod(Invoker.java:580)
      at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:716)
      at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:988)
      at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
      at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
      at org.testng.TestRunner.privateRun(TestRunner.java:648)
      at org.testng.TestRunner.run(TestRunner.java:505)
      at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
      at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
      at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
      at org.testng.SuiteRunner.run(SuiteRunner.java:364)
      at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
      at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
      at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
      at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
      at org.testng.TestNG.runSuites(TestNG.java:1049)
      at org.testng.TestNG.run(TestNG.java:1017)
      at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
      at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
  Caused by: java.lang.IllegalArgumentException: Cannot deserialize Class io.inbot.common.ObjectMapperTest$should handle generics$Outer (of type local/anonymous) as a Bean
      at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.isPotentialBeanType(BeanDeserializerFactory.java:877)
      at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:131)
      at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:411)
      at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
      at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
      ... 31 more
  </code></pre>
  
  <p>Obviously the jackson plugin for kotlin does not handle this. Is there a workaround for this or a different way of doing this?</p>
  
  <p>BTW. the stringify function is a simple extension function I added for ObjectMapper that takes care of the boilerplate code:</p>
  
  <pre><code>/**
   * Serializes [value] to a string. Pretty prints if [pretty] is set.
   */
  fun &lt;T&gt; ObjectMapper.stringify(value: T, pretty: Boolean = false): String {
      val bos = ByteArrayOutputStream()
      val writer = OutputStreamWriter(bos, StandardCharsets.UTF_8)
      if(pretty) {
          writerWithDefaultPrettyPrinter().writeValue(writer,value)
      } else {
          writeValue(writer, value)
      }
      writer.flush()
      bos.flush()
      return bos.toByteArray().toString(StandardCharsets.UTF_8)
  }
  </code></pre>
  
  <p><strong>UPDATE</strong> The code in the answer by @jayson-minard works. It turns out that the key difference with my code was that I defined the data classes inside the test method. Moving them outside to the top level fixes things. Putting a dataclass in a function was a bad idea to begin with.</p>