使用Jackson将JSON反序列化为ArrayList <POJO>

tac*_*cos 81 java mapping json jackson

我有一个Java类MyPojo,我有兴趣从JSON反序列化.我已经配置了一个特殊的MixIn类MyPojoDeMixIn,以帮助我进行反序列化.MyPojo只有intString实例变量结合适当的getter和setter.MyPojoDeMixIn看起来像这样:

public abstract class MyPojoDeMixIn {
  MyPojoDeMixIn(
      @JsonProperty("JsonName1") int prop1,
      @JsonProperty("JsonName2") int prop2,
      @JsonProperty("JsonName3") String prop3) {}
}
Run Code Online (Sandbox Code Playgroud)

在我的测试客户端中,我执行以下操作,但当然它在编译时不起作用,因为存在JsonMappingException与类型不匹配相关的问题.

ObjectMapper m = new ObjectMapper();
m.getDeserializationConfig().addMixInAnnotations(MyPojo.class,MyPojoDeMixIn.class);
try { ArrayList<MyPojo> arrayOfPojo = m.readValue(response, MyPojo.class); }
catch (Exception e) { System.out.println(e) }
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过创建一个只包含其中的"Response"对象来缓解这个问题ArrayList<MyPojo>,但是我必须为我想要返回的每个类型创建这些有些无用的对象.

我还在线查看了JacksonInFiveMinutes,但是很难理解有关Map<A,B>我的问题以及它与我的问题有什么关系.如果你不能说,我是Java的新手,来自Obj-C背景.他们特别提到:

除了绑定到POJO和"简单"类型之外,还有一个附加变体:绑定到通用(类型)容器的变体.这种情况需要特殊处理,因为所谓的类型擦除(Java用于以某种向后兼容的方式实现泛型),这会阻止您使用类似Collection.class(不能编译)的东西.

因此,如果要将数据绑定到Map,则需要使用:

Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });
Run Code Online (Sandbox Code Playgroud)

我怎样才能直接反序列化ArrayList

Per*_*ion 133

您可以使用TypeReference包装器直接反序列化到列表.一个示例方法:

public static <T> T fromJSON(final TypeReference<T> type,
      final String jsonPacket) {
   T data = null;

   try {
      data = new ObjectMapper().readValue(jsonPacket, type);
   } catch (Exception e) {
      // Handle the problem
   }
   return data;
}
Run Code Online (Sandbox Code Playgroud)

因此使用:

final String json = "";
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json);
Run Code Online (Sandbox Code Playgroud)

.

TypeReference Javadoc

  • @JsonProperty并不像人们所做的那样邪恶.使用当前的标准化状态(最小化),很难摆脱供应商特定的注释. (2认同)

Dev*_*vNG 88

另一种方法是使用数组作为类型,例如:

ObjectMapper objectMapper = new ObjectMapper();
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class);
Run Code Online (Sandbox Code Playgroud)

这样你可以避免使用Type对象的所有麻烦,如果你真的需要一个列表,你总是可以通过以下方式将数组转换为列表:

List<MyPojo> pojoList = Arrays.asList(pojos);
Run Code Online (Sandbox Code Playgroud)

恕我直言,这更具可读性.

并使其成为一个实际列表(可以修改,请参阅限制Arrays.asList()),然后执行以下操作:

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos));
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案,简单且更具可读性. (6认同)

Дми*_*шов 25

这种变体看起来更简单和优雅.

CollectionType typeReference =
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class);
List<Dto> resultDto = objectMapper.readValue(content, typeReference);
Run Code Online (Sandbox Code Playgroud)


Jug*_*hal 7

这对我有用。

@Test
public void cloneTest() {
    List<Part> parts = new ArrayList<Part>();
    Part part1 = new Part(1);
    parts.add(part1);
    Part part2 = new Part(2);
    parts.add(part2);
    try {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonStr = objectMapper.writeValueAsString(parts);

        List<Part> cloneParts = objectMapper.readValue(jsonStr, new TypeReference<ArrayList<Part>>() {});
    } catch (Exception e) {
        //fail("failed.");
        e.printStackTrace();
    }

    //TODO: Assert: compare both list values.
}
Run Code Online (Sandbox Code Playgroud)