activateDefaultTyping does not work with inner class in a collection like ArrayList
See original GitHub issueFound in Jackson 2.11.2. Suppose we put a some objects into a list then serialize it. If the object is from a normal class, everything works. But if it’s an inner class, the type of each element is erased as “java.util.Object”. If you have bean wrapper to the ArrayList, or if you define the MyObj class as a standard alone class (not an inner class), it will work.
Below is the test class.
@Test
public void test() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(new DefaultBaseTypeLimitingValidator(), ObjectMapper.DefaultTyping.EVERYTHING, JsonTypeInfo.As.PROPERTY);
List<MyObj> list = new ArrayList<>();
MyObj o1 = new MyObj();
o1.v1 = 1;
list.add(o1);
String json = mapper.writeValueAsString(list);
System.out.println(json);
// it prints ["java.util.ArrayList",[{"@class":"java.lang.Object","v1":1}]]
}
class MyObj {
int v1;
public int getV1() {
return v1;
}
public void setV1(int v1) {
this.v1 = v1;
}
}
If you look at the ClassNameIdResolver, when we see an inner class, I don’t quite understand the logic here, anyway the str loses valuable information about the actual class name, becomes “java.util.Object”. Why do we use the base type? why not using the actual class name here?
} else if (str.indexOf('$') >= 0) {
/* Other special handling may be needed for inner classes,
* The best way to handle would be to find 'hidden' constructor; pass parent
* value etc (which is actually done for non-anonymous static classes!),
* but that is just not possible due to various things. So, we will instead
* try to generalize type into something we will be more likely to be able
* construct.
*/
Class<?> outer = ClassUtil.getOuterClass(cls);
if (outer != null) {
// one more check: let's actually not worry if the declared static type is
// non-static as well; if so, deserializer does have a chance at figuring it all out.
Class<?> staticType = _baseType.getRawClass();
if (ClassUtil.getOuterClass(staticType) == null) {
// Is this always correct? Seems like it should be...
cls = _baseType.getRawClass();
str = cls.getName();
}
}
}
return str
Issue Analytics
- State:
- Created 3 years ago
- Comments:5 (4 by maintainers)
Top Results From Across the Web
Can't add a value to ArrayList because it's in an Inner Class?
I am writing a file that can parse rdf and owl files. I am using SAX and Java. My problem is on the...
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 >Nested Classes - Learning the Java Language
Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes...
Read more >Inner/Nested Classes Collection Implementation
So A implements the code, gives something to B, where B can invoke the code later. • Inner classes are widely used to...
Read more >An inner class - Cornell CS
ArrayList s contains one object of static nested class Entry for each integer in the set; that object contains the integer and the...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
There is one test class,
TestAbstractTypeNames
, which has this as use case:I am not 100% sure if this is actually in use: from comment in test it looks like original issue was against Jackson 1.x so probably 8+ years ago…
However, at this point I don’t feel like it should be blocked for 2.x. But I will remove handling from 3.0.
I think earlier code may have thrown an exception (as I agree it is good to indicate invalid use cases). But unfortunately I am not sure it is possible to detect definitely invalid usage. I think the expected working case is something like:
where anonymous non-static inner class is to be written and logic can figure out type to use can be
ArrayList
.The other possibility is that sometimes users only serialize things using Jackson and use something else for reading content.
It may be easy enough to test to see what happens if code is changed to throw an exception in assumed bad case and running unit tests. I think a test would fail, showing expected correct usage.