【问题标题】:Deserializing into a HashMap of custom objects with jackson使用杰克逊反序列化为自定义对象的 HashMap
【发布时间】:2013-08-02 20:28:01
【问题描述】:

我有以下课程:

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.annotate.JsonProperty;

import java.io.Serializable;
import java.util.HashMap;

@JsonIgnoreProperties(ignoreUnknown = true)
public class Theme implements Serializable {

    @JsonProperty
    private String themeName;

    @JsonProperty
    private boolean customized;

    @JsonProperty
    private HashMap<String, String> descriptor;

    //...getters and setters for the above properties
}

当我执行以下代码时:

    HashMap<String, Theme> test = new HashMap<String, Theme>();
    Theme t1 = new Theme();
    t1.setCustomized(false);
    t1.setThemeName("theme1");
    test.put("theme1", t1);

    Theme t2 = new Theme();
    t2.setCustomized(true);
    t2.setThemeName("theme2");
    t2.setDescriptor(new HashMap<String, String>());
    t2.getDescriptor().put("foo", "one");
    t2.getDescriptor().put("bar", "two");
    test.put("theme2", t2);
    String json = "";
    ObjectMapper mapper = objectMapperFactory.createObjectMapper();
    try {
        json = mapper.writeValueAsString(test);
    } catch (IOException e) {
        e.printStackTrace(); 
    }

生成的 json 字符串如下所示:

{
  "theme2": {
    "themeName": "theme2",
    "customized": true,
    "descriptor": {
      "foo": "one",
       "bar": "two"
    }
  },
  "theme1": {
    "themeName": "theme1",
    "customized": false,
    "descriptor": null
  }
}

我的问题是把上面的 json 字符串反序列化成一个

HashMap<String, Theme> 

对象。

我的反序列化代码如下:

HashMap<String, Themes> themes =
        objectMapperFactory.createObjectMapper().readValue(json, HashMap.class);

使用正确的键反序列化为 HashMap,但不会为值创建主题对象。我不知道在 readValue() 方法中指定什么来代替“HashMap.class”。

任何帮助将不胜感激。

【问题讨论】:

    标签: java jackson json-deserialization


    【解决方案1】:

    您应该创建特定的 Map 类型并将其提供给反序列化过程:

    TypeFactory typeFactory = mapper.getTypeFactory();
    MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, Theme.class);
    HashMap<String, Theme> map = mapper.readValue(json, mapType);
    

    【讨论】:

    • 好的,我们肯定在朝着正确的方向前进,因为它正在使用上面的代码进行反序列化。但是,哈希图仅带有单个键/值(主题2)。它确实具有与键关联的正确主题,但 theme1 不在 hashmap 中?
    • 为什么不呢。对我来说,当我反序列化您的 JSON 时,应用程序会打印:'{theme1=Theme [themeName=theme1,customized=false,descriptor=null],theme2=Theme [themeName=theme2,customized=true,descriptor={foo=one, bar=two}]}'。
    • 发现问题 - 我的测试数据中的 json 字符串格式不正确。所以你的解决方案就像宣传的那样工作;)
    • 我也可以只使用 Jackson 注释吗?
    【解决方案2】:

    您可以使用 TypeReference 类对用户定义类型的映射进行类型转换。更多文档https://github.com/FasterXML/jackson-databind/

    ObjectMapper mapper = new ObjectMapper();
    Map<String,Theme> result =
      mapper.readValue(src, new TypeReference<Map<String,Theme>>() {});
    

    【讨论】:

      【解决方案3】:

      您可以制作一个扩展地图的 POJO。

      这对于处理对象的嵌套映射很重要。

      {
        key1: { nestedKey1: { value: 'You did it!' } }
      }
      

      这可以通过以下方式反序列化:

      class Parent extends HashMap<String, Child> {}
      
      class Child extends HashMap<String, MyCoolPojo> {}
      
      class MyCoolPojo { public String value; }
      
      Parent parent = new ObjectMapper().readValue(json, Parent.class);
      parent.get("key1").get("nestedKey1").value; // "You did it!"
      

      【讨论】:

        猜你喜欢
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-31
        • 2016-01-08
        • 1970-01-01
        相关资源
        最近更新 更多