How to serialize generic/polymorphic objects starting with 2.12.0-rc2? #4075
-
Hello community! Recently I raised jackson-databind version in my project because of vulnerabilities and ran into something unexpected. I have this code (it's synthetic just for illustration, but it has the same structure as in the project code): import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import java.io.Serializable;
public class Main {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JustT<Method> t = new JustT<>(new MedianMethod());
System.out.println(mapper.writeValueAsString(t));
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = MeanMethod.class, name = "Mean"),
@JsonSubTypes.Type(value = MedianMethod.class, name = "Median") })
interface Method extends Serializable {
}
class MeanMethod implements Method {
}
class MedianMethod implements Method {
}
@AllArgsConstructor
class JustT<T> {
private T o;
@JsonValue
public Object getValue() {
return o;
}
} With jackson-databind 2.12.0-rc1 and below the output is:
But with jackson-databind 2.12.0-rc2 and above it is:
Why is that? How to keep the type in a serialized value? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
@piakbt Idk what changed between the two Can you try below Java code? Below works in latest
public void testSer() throws Exception {
// provide typeReference
ObjectWriter writer = new ObjectMapper()
.writerFor(new TypeReference<JustT<Base>>(){});
String output = writer.writeValueAsString(new JustT<Base>(new MedianMethod()));
assertEquals("{\"type\":\"Median\"}", output);
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = MeanMethod.class, name = "Mean"),
@JsonSubTypes.Type(value = MedianMethod.class, name = "Median") })
interface Base extends Serializable {
}
class MeanMethod implements Base {
}
class MedianMethod implements Base {
}
class JustT<T> {
private T o;
// Instead of Object, use T here
@JsonValue
public T getValue() {
return o;
}
public JustT(T o) {
this.o = o;
}
} Wrt vulnerabilities, I would recommend upgrade to latest stable version |
Beta Was this translation helpful? Give feedback.
-
One minor note: use of And as an additional sidenote: while there are questions of versions compatibility, it is usually not a good way to ask about behavioral change as much as whether the later version has expected behavior -- behavior is, after all, typically changed when a bug is fixed. It might be regression (breakage), but ultimately the question is whether observed new behavior is (more) correct or not. Put another way: only report bugs for changes where the new behavior appears incorrect, and focus on showing the problem. Not asking about change in behavior. I mention above things because they seem to be recurring challenges with bug requests and discussions: not because this one was particularly problematic. |
Beta Was this translation helpful? Give feedback.
@piakbt Idk what changed between the two
2.12.0-rc
versions though.Can you try below Java code? Below works in latest
jackson-databind 2.12
branch. To point out the difference....writerFor(new TypeReference<JustT<Base>>(){})
, and@JsonValue
annotated method returns T. Check out @JsonValue documentation