Imagine that I have an abstract class named InfoItem
, that each class that inherits from it is a different type of Info Type that is used later to help me with the classification.
Each InfoItem
have a timestamp
as a property (when does this InfoItem
arrive )?
Note: I'm using Lombok in this example
@Data
@JsonTypeInfo(use = Id.NAME, visible = true, property = "@type")
public abstract class InfoItem {
private LocalDateTime timestamp;
}
I have 2 classes that extend this class: Alpha
and Beta
.
Each class has multiple properties that don't have a common property between them:
@JsonTypeName("alpha")
@Data
public class Alpha extends InfoItem {
private int x;
private long y;
}
@JsonTypeName("beta")
@Data
public class Beta extends InfoItem {
private bool isOk;
}
Now imagine that I create a list of InfoItem
items:
list[0] = Alpha(x = 10, y = 20)
list[1] = Beta(isOk = false)
If the list above is saved as a variable named lst
, and then I'd run this command:
ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(lst);
System.out.println(s);
I'd get this:
[
{
"x": 10,
"y": 20
},
{
"isOk": false
}
]
instead of:
[
{
"@type": "alpha",
"x": 10,
"y": 20
},
{
"@type": "beta",
"isOk": false
}
]
It happens when I run the ObjectMapper
over a List
directly, and not a class that I create and put in it a list.
If I create a class named FooBar
that have a property lst
(type List` - same as above):
@Data
public class FooBar {
private List<InfoItem> items;
}
and then I do:
FooBar bar = new FooBar();
bar.setItems(lst);
ObjectMapper mapper = new ObjectMapper();
String s = mapper.writeValueAsString(lst);
System.out.println(s);
I'd get:
{
"items": [
{
"@type": "alpha",
"x": 10,
"y": 20
},
{
"@type": "beta",
"isOk": false
}
]
}
I've found after a few days a solution:
public static <T> Optional<String> toJson(final ObjectMapper mapper, final TypeReference<T> type, final T object) {
try {
return Optional.ofNullable(mapper.writer().forType(type).writeValueAsString(object));
} catch (JsonProcessingException e) {
return Optional.empty();
}
}
public static void main(String[] args) {
List<InfoItem> items = new ArrayList<>();
// Set values in items...
ObjectMapper mapper = new ObjectMapper();
Optional<String> json = toJson(mapper, new TypeReference<List<InfoItem>>() {}, items);
json.ifPresent(x -> System.out.println(x));
}