使用Java中的Jackson将JSON数组反序列化为Map

时间:2014-08-22 11:40:17

标签: serialization map jackson deserialization arrays

我使用了速度更快的XML的Jackson(v2.3.3)库来反序列化和序列化自定义类。该类定义如下:

public class Person {

  private String name;
  private Map<String, Person> children;

  // lots of other fields of different types with no issues
}

地图children的键是name字段。我在JSON中接收数据,每个人对象的结构如下(我省略了其他字段):

{"name":"Bob", "children":[{"name":"Jimmmy"},{"name":"Judy"}]}

(许多字段,例如子字段是可选的,并且在null时不被序列化)

到目前为止,我一直将孩子存储在List<Person>中没有任何问题,但许多新的用例需要使用他的名字作为密钥来访问这组名称或特定的人员。这就是我决定使用Map存储它们的原因。

经过一些研究后,我认为最好的方法是使用注释@JsonDeserialize@JsonSerialize分别以JsonDeserializerJsonSerializer为参数为字段子项:

public class Person {

  private String id;

  @JsonSerialize(using=MySerializer.class)
  @JsonDeserialize(using=MyDeserializer.class)
  private Map<String, Person> friends;

  // lots of other fields
}

我的问题是:这样的JsonSerializer / JsonDeserializer是否存在,如果不存在,我该如何定义一个?


编辑:我已经开始实现自定义反序列化器,但是我得到了这个例外:

com.fasterxml.jackson.databind.JsonMappingException: Class has no default (no arg) constructor

这很奇怪,因为我已经定义了一个默认的构造函数。这是我的自定义反序列化器:

public class MyDeserializer extends JsonDeserializer<Map<String, Person>> {

    public MyDeserializer() {
    }

    @Override
    public Map<String, Person> deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
      JsonNode personsNodeArray = jp.getCodec().readTree(jp);
      Map<String, Person> newChildren = null;
      if (personsNodeArray.isArray() && personsNodeArray.size() > 0) {
        newChildren = new HashMap<String, Person>();
        for (JsonNode personNode : personsNodeArray) {
          String id = personNode.get("name").asText();
          // jsonMapper is a default ObjectMapper
          newChildren.put(id, jsonMapper.readValue(personNode.toString(), Person.class));
        }
      }
      return newChildren;
    }
  }

1 个答案:

答案 0 :(得分:1)

您还可以考虑将儿童信息作为人员集合进行阅读,然后将其转换为地图。您可以定义setter方法(或构造函数参数)以接受List<Person>,然后将每个元素放入Map<String, Person> children字段。这样可以避免不必要的自定义序列化复杂化。

以下是一个例子:

public class JacksonChildren {
    public static final String JSON = "{\"name\":\"Bob\", \"children\":[{\"name\":\"Jimmmy\"}," +
            "{\"name\":\"Judy\"}]}";

    public static class Person {
        public String name;
        private Map<String, Person> children = new HashMap<>();

        public void setChildren(final List<Person> children) {
            for (Person p : children) {
                this.children.put(p.name, p);
            }
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", children=" + children +
                    '}';
        }
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.readValue(JSON, Person.class));
    }

}

输出:

Person{name='Bob', children={Judy=Person{name='Judy', children={}}, Jimmmy=Person{name='Jimmmy', children={}}}}