Cannot deserialize XML with Polymorphisme and Collections

138 views
Skip to first unread message

Audrey Romanet

unread,
Sep 27, 2017, 11:38:36 AM9/27/17
to jackson-user
Hello,

I am trying to deserialize a rather complex Object, but I always got a "com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token"

I have an abstract class, with two implementations. 
This abstract class has a "value" field, which can be either a "simple" object (such as a String, an int, etc) or a collection (a List of items).

I'm able to deserialize my XML when I have a simple object, but it is failing with a collection.

If my collection is not in an abstract class, there is no issue. But it seems to be not possible to have an abstract class with a field being either a collection or not.

What I am missing ?

Thanks

Here is a unit test reproducing the problem:

public class DeserializationXmlTest {

 
@Test
 
public void deserializeXml_simple() throws IOException {
   
ObjectMapper objectMapper = new XmlMapper();

   
Pojo readValue = objectMapper.readValue("<root>" +
     
"<name>MyName</name>" +
     
"<field>" +
     
" <value>MyValue</value>" +
     
" <type>SIMPLE</type>" +
     
"</field>" +
     
"</root>", Pojo.class);

   assertThat
(readValue.name).isEqualTo("MyName");
   assertThat
(readValue.field).isInstanceOf(SimpleValue.class);
   assertThat
(readValue.field.type).isEqualTo("SIMPLE");
   assertThat
(readValue.field.value).isEqualTo("MyValue");
 
}

 
@Test
 
public void deserializeXml_list() throws IOException {
   
ObjectMapper objectMapper = new XmlMapper();

   
Pojo readValue = objectMapper.readValue("<root>" +
     
"<name>MyName</name>" +
     
"<field>" +
     
" <value>" +
     
" <item>Value1</item>" +
     
" <item>Value2</item>" +
     
" </value>" +
     
" <type>LIST</type>" +
     
"</field>" +
     
"</root>", Pojo.class);

   assertThat
(readValue.name).isEqualTo("MyName");
   assertThat
(readValue.field).isInstanceOf(ListValue.class);
   assertThat
(readValue.field.type).isEqualTo("LIST");
   assertThat
(readValue.field.value).isEqualTo(Arrays.asList("Value1", "Value2"));
 
}

 
@Test
 
public void deserializeXml_list_no_abstract() throws IOException {
   
ObjectMapper objectMapper = new XmlMapper();

   
Pojo readValue = objectMapper.readValue("<root>" +
     
"<name>MyName</name>" +
     
"<listValue>" +
     
" <value>" +
     
" <item>Value1</item>" +
     
" <item>Value2</item>" +
     
" </value>" +
     
"</listValue>" +
     
"</root>", Pojo.class);

   assertThat
(readValue.name).isEqualTo("MyName");
   assertThat
(readValue.listValue).isInstanceOf(NoAbstractListValue.class);
   assertThat
(readValue.listValue.value).isEqualTo(Arrays.asList("Value1", "Value2"));
 
}

 
@JacksonXmlRootElement(localName = "root")
 
@JsonIgnoreProperties(ignoreUnknown = true)
 
public static class Pojo {
   
@JsonProperty
   
private String name;
   
@JsonProperty
   
private AbstractValue field;
   
@JsonProperty(required = false)
   
private NoAbstractListValue listValue;
 
}

 
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
 
@JsonSubTypes({
   
@JsonSubTypes.Type(value = SimpleValue.class, name = "SIMPLE"),
   
@JsonSubTypes.Type(value = ListValue.class, name = "LIST")
 
})
 
public static class AbstractValue<T> {
   
protected String type;
   
protected T value;
   
public AbstractValue(String type) {
     
this.type = type;
   
}
 
}

 
public static class SimpleValue extends AbstractValue<String> {
   
public SimpleValue() {
     
super("SIMPLE");
   
}

   
@JsonProperty
   
public void setValue(String value) {
     
this.value = value;
   
}
 
}

 
public static class ListValue extends AbstractValue<List<String>> {
   
public ListValue() {
     
super("LIST");
   
}

   
@JsonProperty
   
@JacksonXmlElementWrapper(localName = "value")
   
@JacksonXmlProperty(localName = "item")
   
public void setValue(List<String> value) {
     
this.value = value;
   
}
 
}

 
public static class NoAbstractListValue {
   
protected List<String> value;

   
public NoAbstractListValue() {
   
}

   
@JsonProperty
   
@JacksonXmlElementWrapper(localName = "value")
   
@JacksonXmlProperty(localName = "item")
   
public void setValue(List<String> value) {
     
this.value = value;
   
}
 
}
}

When running this test, the deserializeXml_simple and deserializeXml_list_no_abstract will succeed, but not deserializeXml_list.

Reply all
Reply to author
Forward
0 new messages