question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Deserialize list of array failed with enableDefaultTyping

See original GitHub issue

I use the same ObjectMapper instance to serialize and deserialize List<String[]>, deserialization failed with all of DefaultTyping’s, and same as List<Integer[]>, tested with the latest version 2.9.6.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper = objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT,
			JsonTypeInfo.As.PROPERTY);
List<String[]> list = new ArrayList<>();
list.add(new String[] { "test" });
String s = objectMapper.writeValueAsString(list); // [["[Ljava.lang.String;",["test"]]]
List<String[]> list2 = objectMapper.readValue(s, new TypeReference<List<String[]>>() {
});
System.out.println(Arrays.equals(list.get(0), list2.get(0)));
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token
 at [Source: (String)"[["[Ljava.lang.String;",["test"]]]"; line: 1, column: 25] (through reference chain: java.util.ArrayList[0]->java.lang.Object[][1])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1138)
	at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1092)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseString(StdDeserializer.java:569)
	at com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer.deserialize(StringArrayDeserializer.java:157)
	at com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer.deserialize(StringArrayDeserializer.java:21)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3023)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
cowtowncodercommented, Jul 26, 2018

I think the problem is Java Type Erasure with root values: you are serializing something only seen as List<?> (due type erasure), and type information is included for elements as they are nominally of type Object (type information checks always use static type, not runtime type). But when reading back you are instructing type to be List<String>` , and thereby entries are not expected to have type information.

In general I would strongly recommend against using generic types like List<X> as root values; and instead use a POJO as wrapper. This avoid most if not all type erasure issues.

If you do want combination to work without changes, however, you will need to force type on serialization. Something like

objectMapper.writerFor(new TypeReference<List<String>>() { })
    .writeValueAsString(list);

or create a non-generic List type:

public class StringList extends ArrayList<String> { }

and use that instead of generic version. This will also work around type erasure.

0reactions
cowtowncodercommented, Nov 20, 2018

Actually the flaw here is call for deserialization: it must use same type information as serialization, to determine proper base type. Specifically, it should NOT try to pass type as List<String[]> since that is not type serializer has access to: due to Java Type Erasure, all it knows is type is List<?>.

So: either writeValue() call has to also pass more specific type information (via mapper.writerFor(new TypeReference<....>) or readValue() should be given less accurate one.

And note that the reason your change also works is that as per configuration, ONLY nominal type of Object will get type information added; Object[] is not Object (nor is String[]). There are other DefaultTyping options (like OBJECT_AND_NON_CONCRETE and NON_FINAL) that could work better as well.

At any rate functionality works as I would expect so I will close the issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Deserializing Java arrays with Jackson - json - Stack Overflow
The best solution I've found for now is checking before serialization if the object is an array (Class.isArray) and then doing the ...
Read more >
cannot deserialize out of start_array token - You.com
Im trying to deserialize a JSON list into a custom class with a list-typed parameter. However, this fails with com.fasterxml.jackson.databind.exc.
Read more >
Inheritance in Jackson | Baeldung
This tutorial will demonstrate how to handle inclusion of subtype metadata and ignoring properties inherited from superclasses with Jackson.
Read more >
Failed to deserialize JSON - OutSystems
The error is correct, the built-in JSON deserializer does not allow you to turn an array of simple types into an Object. You...
Read more >
Jackson Deserialization Vulnerabilities - NCC Group
The enableDefaultTyping method instructs ObjectMapper to include the Java class names for all non- final classes using the default inclusion ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found