使用Jackson序列化/反序列化具有不同类型的映射表

3
我正在尝试以不同方式序列化和反序列化不同类型的地图。我希望...
Map<String, MyInterface> map1;

需要以不同的方式进行序列化和反序列化

Map<String, String> map2;

我创建了两个序列化器

public class MyFirstSerializer extends JsonSerializer<Map<String, Property>> {
    ...
}

并且

public class MySecondSerializer extends JsonSerializer<Map<String, String>> {
    ...
}

以及两个反序列化器

public class MyFirstDeserializer extends JsonDeserializer<Map<String, Property>> {
    ...
}

并且

public class MySecondDeserializer extends JsonDeserializer<Map<String, String>> {
    ...
}

然后我将它们添加到我的模块中,并指定类型:

SimpleModule module = new SimpleModule("MyModule", new Version(1, 0, 0, "beta"));
module.addSerializer(new MyFirstSerializer());
module.addDeserializer((Class<Map<String, Property>>) (Class<?>) Map.class, new MyFirstDeserializer());

module.addSerializer(new MySecondSerializer());
module.addDeserializer((Class<Map<String, String>>) (Class<?>) Map.class, new MySecondDeserializer());

问题是,有时候将类型为 的映射传递给MyFirstSerializer,有时将类型为 的映射传递给MySecondSerializer

我认为问题在于,地图的类型在运行时被擦除,并且没有办法区分这两个不同的地图。我该如何解决这个问题?
我已经查看了Serialize/Deserialize Map<String, Object> with Jackson,但找不到解决方案。

也许定义自己的类型以避免它们被擦除,例如 public class MyInterfaceMap extends Map<String, MyInterface> { ... },然后根据您的类型创建您的(反)序列化器 public class MyFirstSerializer extends JsonSerializer<MyInterfaceMap> { ... },可能会起作用。 - walen
@walen 这就是我得出的解决方案。如果没有其他的解决方案,我最终会采取这个方案,所以请随意添加答案。 - Ian2thedv
1个回答

4

我认为您可以使用 jackson.core.type.TypeReference 来完成这种工作:

Map<String, Property> parsed = 
    objectMapper.readValue(
        jsonString, 
        new TypeReference<Map<String, Property>>() {}
    );

TypeReference 能够在运行时存储泛型类型参数,使 jackson 能够推断值类型并正确反序列化,而不需要自定义 (de)serializers。

另一种方法是使用明确定义的 com.fasterxml.jackson.databind.type.CollectionType 来反序列化json:

CollectionType collectionType =
    objectMapper.getTypeFactory()
        .constructMapType(Map.class, String.class, Property.class);
List<Map<String, Property>> objects = 
    mapper.readValue(jsonString, collectionType);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接