如何 serialize/deserialize 反对映射

How to serialize/deserialize object to Map

我有一个具体案例。我需要 serialize/deserialize 一个对象到 Map<String, Object>。我有一个如下所示的 class:

public class Data {
    public String name;
    public Map<String, Object> options = new HashMap<>();
}

我可以将任何类型的对象放入此选项。例如:

public class Option {
    public int id;
    ...
}

public class TestOpt {
    public name;
    ...
}

然后我尝试对其进行序列化和反序列化:

public static void main(String... args) {
    ObjectMapper mapper = new ObjectMapper();
    Option o = new Option();
    o.id = 1;
    TestOpt t = new TestOpt();
    t.name = "fff";
    Data data = new Data();
    data.name = "data";
    data.options.put("o", o);
    data.options.put("t", t);
    String json = mapper.writeValueAsString(data);

    Data d1 = mapper.readValue(json, Data.class);
    // I get error because options.get("o") contains LinkedHashMap instead of Option.class
    System.out.println(((Option)d1.options.get("o")).id);
}

我该如何解决这个问题?

序列化后的值json

{"name":"data","options":{"t":{"name":"fff"},"o":{"id":1}}}

所以,问题是对象映射器无法判断 json 中的 o 值是一个 Option。最好的猜测是它可能是一张地图,因此它被反序列化为 LinkedHashMap.

如果您确定元素 o 是一个 Option,您可以使用对象映射器转换该值:

Option option = mapper.convertValue(d1.options.get("o"), Option.class);

但请注意,这意味着该值将再次序列化,然后使用正确的类型信息进行反序列化。你可以这样做,但这不是一个好的解决方案。

如果可能,更好的方法是将您的模型从通用映射更改为包含类型信息的特定 class:

class Data {
    public String name;
    public DataOptions options = new DataOptions();
}

class DataOptions {
    public Option o;
    public TestOpt t;
}

序列化此模型与使用地图的模型具有相同的 json 表示,并且该模型可用于反序列化示例中的 json。