2

这是我第一次处理类型映射,每次我尝试将节点映射到我的实际类型对象,它有一个自定义属性键作为 FooType 和一个Set<Integer>值。这是我的对象的样子

public class Foo {
    private String some;
    Map<FooTypes,Set<Integer>> foos;

    public Map<FooTypes, Set<Integer>> getFoos() {
        return foos;
    }
    public void setFoos(Map<FooTypes, Set<Integer>> map) {
        this.foos = map;
    }
    public String getSome() {
        return some;
    }
    public void setSome(String some) {
        this.some = some;
    }
}

public class FooTypes {
    private String name;
    private String id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
}

现在每次我尝试使用映射器来读取值:-

List <Foo> response = mapper.readValue("/home/foo/foo.json",List.class);

我收到一条错误消息:-

Can not find a (Map) Key deserializer for type [simple type, class cruft.FooTypes]

有人可以告诉我如何解决这个问题吗?谢谢你。

json输出:-

{"foos":{"FooTypes [id=1, name=Test Foo]":[1,2,3]},"some":hello},{"foos":{"FooTypes [id=2, name=Another foo]":[5,6,7]}}
4

2 回答 2

8

由于我们没有您想要反序列化的 Json 结构,因此有点难以为您提供帮助,但这里的问题是 Jackson 不知道在将您的类用作映射键时如何反序列化它。Jackson 的所有信息都是一个简单的字符串,而您的类无法仅使用字符串来创建它。

有3种方法可以实现:

  1. 将单个字符串参数构造函数添加到 FooType 类
  2. 添加单个字符串参数工厂方法(静态)并使用 @JsonCreator 对其进行注释
  3. 使用自定义KeyDeserializer并使用注释foos字段@JsonDeserialize(keyUsing=YourDeserializer.class)

恕我直言,静态工厂方法是更清洁的方法。

于 2012-08-30T17:25:23.430 回答
2

由于您将非原始类型作为映射键 ( FooTypes),因此您需要编写自己的自定义反序列化器,如Jackson wiki中所述,因为 Jackson 不能简单地将字符串值"FooTypes [id=1, name=Test Foo]"(这似乎是 的结果FooTypes.toString())转换为FooTypes实例。

在我看来,使用非字符串键序列化映射并不是一个好习惯。JSON 表示法不支持映射键的字符串(如在此处指定)。我认为,更好的方法是在序列化之前和反序列化之后重新组织您的数据结构。

于 2012-08-30T11:51:27.210 回答