使用任意键将JSON反序列化为Map

时间:2014-05-12 11:57:50

标签: java json jackson

我有一个像

这样的结构的不可变JSON
{
  "data": "mydata",
  "information": [
    {
      "info": "mnkjshdflkj",
      "stuff": "things"
    },
    {
      "info": "khsjfdaksdfh",
      "stuff": "more things"
    }
  ]
}

我正在使用Jackson进行反序列化。我想要实现的是以这种格式将这些信息存储在POJO中。

MyData.java

public class MyData {
     String data;
     HashMap<String, Info> information; 
}

信息

public class Info {
     String info; // is it required?
     String stuff;
}

我的地图键是信息字段中的值,值将是类本身。杰克森对这个过程的态度是什么?

1 个答案:

答案 0 :(得分:2)

如果我理解正确,这应该有效。首先为信息字段创建自定义反序列化器。

public class CustomDeserializer extends JsonDeserializer<Map<String, Info>> {
    @Override
    public Map<String, Info> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        List<Info> raw = jp.readValueAs(new TypeReference<List<Info>>() {
        });
        Map<String, Info> result = new HashMap<>();
        for (Info info : raw) {
            result.put(info.getInfo(), info);
        }

        return result;
    }
}

然后你需要注册这个解串器。您可以借助信息字段中的注释来完成此操作。或者以不同的方式注册反序列化器。

@JsonDeserialize(using = CustomDeserializer.class)
    Map<String, Info> information;

要测试的完整代码:

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.type.TypeReference;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
public static void main(String[] args) throws IOException {
    String json = "{\n" +
            "  \"data\": \"mydata\",\n" +
            "  \"information\": [\n" +
            "    {\n" +
            "      \"info\": \"mnkjshdflkj\",\n" +
            "      \"stuff\": \"things\"\n" +
            "    },\n" +
            "    {\n" +
            "      \"info\": \"khsjfdaksdfh\",\n" +
            "      \"stuff\": \"more things\"\n" +
            "    }\n" +
            "  ]\n" +
            "}";

    ObjectMapper mapper = new ObjectMapper();
    MyData data = mapper.readValue(json, MyData.class);
    System.out.println(data);
}

public static class MyData {
    String data;
    @JsonDeserialize(using = CustomDeserializer.class)
    Map<String, Info> information;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public Map<String, Info> getInformation() {
        return information;
    }

    public void setInformation(Map<String, Info> information) {
        this.information = information;
    }

    @Override
    public String toString() {
        return "MyData{" +
                "data='" + data + '\'' +
                ", information=" + information +
                '}';
    }
}

public static class Info {
    String info; // is it required?
    String stuff;

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getStuff() {
        return stuff;
    }

    public void setStuff(String stuff) {
        this.stuff = stuff;
    }

    @Override
    public String toString() {
        return "Info{" +
                "info='" + info + '\'' +
                ", stuff='" + stuff + '\'' +
                '}';
    }
}

public static class CustomDeserializer extends JsonDeserializer<Map<String, Info>> {
    @Override
    public Map<String, Info> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        List<Info> raw = jp.readValueAs(new TypeReference<List<Info>>() {
        });
        Map<String, Info> result = new HashMap<>();
        for (Info info : raw) {
            result.put(info.getInfo(), info);
        }

        return result;
    }
   }
 }