title: Detect object type during deserialization based on xml document properties in Jackson - no JsonNode
body: <p>I have an <code>XML</code> document that I want to deserialise into an object of a class that I do not know during compilation and the type is determined by both the root element name of the document and a <code>type</code> element text content. The problem is twofold:</p>
  
  <ol>
  <li><p>I have element lists in my <code>XML</code> document so I can't parse it to <code>JsonNode</code>/<code>Map</code> because in the best case scenario it will only provide me with the last value on the list, the information is lost in the process. All the solutions I found rely on <code>JsonNode</code> <code>API</code> (like <code>convertValue</code> or <code>treeToValue</code>).</p></li>
  <li><p>I can't use <code>JsonTypeInfo</code> - I don't know the concrete classes that will be <code>deserialised</code> and so I cannot use the annotations. Also I don't think <code>JsonTypeInfo</code> is this flexible as to include both root element name and a property value.</p></li>
  </ol>
  
  <p>I tried using a custom deserialiser that would wrap the actual parsed <code>JsonNode</code> into another <code>Object</code> with rootElement as an only key (by default this root element is not included in the parsed document). After that I deserialise the document, get the root element from the node, then take the type element value, combine the two, create the name of the class and then convert the <code>JsonNode</code> to the final object. The problem with this approach is that it doesn't handle the lists well and either throws and exception of invalid mapping or provides me with the last element of the list depending of how I write my model or configure the mapper.
      package zm.study.xmlserialize.jackson;</p>
  
  <pre><code>import static org.junit.Assert.assertEquals;
  
  import java.io.StringReader;
  import java.util.List;
  
  import org.junit.Test;
  
  import com.fasterxml.jackson.core.JsonParser;
  import com.fasterxml.jackson.databind.DeserializationContext;
  import com.fasterxml.jackson.databind.JsonNode;
  import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
  import com.fasterxml.jackson.databind.module.SimpleModule;
  import com.fasterxml.jackson.dataformat.xml.XmlMapper;
  import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
  import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
  
  public class JacksonListTest2 {
   public static class A &lt; D extends AData &gt; {
    public String type;
    public D data;
   }
  
   public static class AData {}
  
   public static class BRequestData extends AData {
    @JacksonXmlElementWrapper(useWrapping = false)
    public List &lt; String &gt; bs;
   }
  
   public static class BRequest extends A {}
  
   @Test
   public void test() throws Exception {
    String xml;
  
    xml = "&lt;Request&gt;&lt;type&gt;B&lt;/type&gt;&lt;data&gt;&lt;bs&gt;1&lt;/bs&gt;&lt;bs&gt;2&lt;/bs&gt;&lt;/data&gt;&lt;/Request&gt;";
  
    XmlMapper mapper = new XmlMapper();
  
    mapper.registerModule(
     new SimpleModule()
     .addDeserializer(JsonNode.class, new JsonNodeDeserializer() {
      @Override
      public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws java.io.IOException {
       String rootName = ((FromXmlParser) p).getStaxReader().getLocalName();
       return ctxt.getNodeFactory().objectNode().set(rootName, super.deserialize(p, ctxt));
      };
     })
    );
  
    JsonNode rootNode = mapper.readTree(new StringReader(xml));
    String rootName = rootNode.fields().next().getKey();
    JsonNode contentNode = rootNode.get(rootName);
    String type = contentNode.get("type").asText();
    String className = getClass().getCanonicalName() + "$" + type + rootName;
  
    BRequest value = (BRequest) mapper.convertValue(contentNode, Class.forName(className));
    System.out.println(value.data.bs);
    assertEquals(2, value.data.bs.size());
   }
  
  }
  </code></pre>
  
  <p>My approach results in throwing exception:</p>
  
  <blockquote>
    <p>Cannot deserialize instance of <code>java.util.ArrayList</code> out of
    VALUE_STRING token</p>
  </blockquote>
  
  <p>I also tried creating a custom deserialiser parsing just enough of the document to find out what type I'm dealing with and then delegating the rest of the actual parsing (the data element) to the default deserialiser but didn't manage to write any sensible code to do it.</p>
  
  <p>I think I need a new approach, any ideas?</p>