I need to serialize and deserialize in JSON format a Java map using the Jackson library.
The map type is Map<Enum<?>, Object>
and its purpose is to store a configuration made by key-value pairs, where keys are enum instances coming from a third party library (hence I do not have control over their definition).
Keys can be enums of different type, whereas values can be int
, double
or String
.
Also, you can assume that different enums have different instance names.
Serialization works fine:
public class Main {
public enum IntParam {I1, I2, I3}
public enum DoubleParam {D1, D2, D3}
public enum StringParam {S1, S2, S3}
public static void main(final String[] args) {
Map<Enum<?>, Object> config = Map.of(
IntParam.I1, 0,
DoubleParam.D2, 1.0,
StringParam.S3, "sss"
);
new ObjectMapper().writeValueAsString(config)
// {"I1": 1, "D2": 1.0, "S3": "sss"}
}
The problem is deserializing the above object:
String json = "{"I1": 1, "D2": 1.0, "S3": "sss"}";
new ObjectMapper().readValue(json, new TypeReference<Map<Enum<?>, Object>>())
fails because Jackson cannot know which enum contains instances named I1
, D2
and S3
.
I would like to achieve something like
{
"com.external.company.IntParam.I1": 1,
"com.external.company.DoubleParam.D2": 1.0,
"com.external.company.StringParam.S3": "sss"
}
during serialization and then be able to deserialize it.
2
Answers
I solved the problem writing a custom deserializer that loads the JSON object in a
HashMap<String, Object>
and then loops through the different enum types looking for the enum instance with the same name as the key in the map (this relies on the fact that all enum instances have different names across all the involved enum types).Finally, I decorated the config property with
An enum and a map don’t seem like the correct tools here (too many problems), I would try to redesign, if at all possible. Still, this can be achieved with wrapper class and custom serializer/deserializer for keys – applying mixin on
Enum
to achieve polymorphic serialization does not seem possible (do not take my word for it though, I may be wrong).A wrapper for the enum:
Notice
keyUsing
, that’s to make the de/serializers used specifically for map keys.A deserializer to preserve information about the enum class and the instance:
A deserializer to parse to correct enum and instance of that enum:
Example: