FasterXML / FasterXML/jackson-databind
Inner classes that get their generic information from an outer class lose type information
- Ngôn ngữ chính
- Java
- Star
- 3.7k
- Fork
- 1.5k
- Merge trung bình
- 3 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 28
Mô tả
**Describe the bug**
If a non-static inner class uses generics from the outer class, that generic information is lost when serializing.
**Version information**
2.12.5
**To Reproduce**
```java
import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
public final class JacksonPoC {
@JsonTypeInfo(use = Id.NAME)
@JsonSubTypes({@JsonSubTypes.Type(value = ConcreteValue.class, name = "concrete-value")})
private interface AbstractValue {}
private static class ConcreteValue implements AbstractValue {}
public interface Wrapper {
T getValue();
}
private static final class Outer {
private final class Inner implements Wrapper {
private final T value;
Inner(T value) {
this.value = value;
}
@Override
public T getValue() {
return value;
}
}
Inner create(T value) {
return new Inner(value);
}
}
private static final class Direct implements Wrapper {
private final T value;
Direct(T value) {
this.value = value;
}
@Override
public T getValue() {
return value;
}
}
private static final class Container {
private final Wrapper wrapper;
Container(Wrapper wrapper) {
this.wrapper = wrapper;
}
public Wrapper getWrapper() {
return wrapper;
}
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void direct() throws Exception {
// This test passes because the generic information is present on the class directly
Container object = new Container(new Direct<>(new ConcreteValue()));
assertThat(mapper.writeValueAsString(object))
.isEqualTo("{\"wrapper\":{\"value\":{\"@type\":\"concrete-value\"}}}");
}
@Test
void indirect() throws Exception {
// This test fails (the @type part is omitted) because the `AbstractValue` information is lost
Container object = new Container(new Outer().create(new ConcreteValue()));
assertThat(mapper.writeValueAsString(object))
.isEqualTo("{\"wrapper\":{\"value\":{\"@type\":\"concrete-value\"}}}");
}
}
```
**Additional context**
The example above does feel quite contrived, but I encountered this in practice with Guava's Multimaps.asMap on a SetMultimap, because the resulting class `AbstractMapBasedMultimap.WrappedSet` inherits the generic information from the parent.
When debugging this, I got as far as the short-circuit in https://github.com/FasterXML/jackson-databind/blob/77e8b62fed4748d19fbd350c9fd80a7bdca75c91/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java#L487, but I'm not sure whether simply removing that is sufficient to resolve this.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Đánh giá
Issue này chưa được đánh giá.