Json Jackson Mapper通用地图类型问题

时间:2012-08-30 06:21:22

标签: java json jackson

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

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;
    }
}

现在每次我尝试使用mapper来读取值: -

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]}}

2 个答案:

答案 0 :(得分:8)

由于我们没有你希望反序列化的Json结构,所以有点难以帮助你,但问题是杰克逊不知道如何将类反序列化时用作地图键< / strong>即可。杰克逊所有的信息都是一个简单的字符串,而你的类只能用一个字符串来创建它。

实现这一目标的方法有三种:

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

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

答案 1 :(得分:2)

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

在我看来,使用非字符串键序列化地图并不是一个好习惯。 JSON表示法不支持除地图键的字符串之外的任何内容(如指定的here)。我认为,更好的方法是在序列化之前和反序列化之后重新组织数据结构。