2012-03-22 256 views
53

我有一个Java类MyPojo,我有兴趣从JSON反序列化。我已经配置了一个特殊的MixIn类,MyPojoDeMixIn,以帮助我进行反序列化。 MyPojo只有intString实例变量与适当的getter和setters组合。 MyPojoDeMixIn看起来是这样的:将JSON反序列化为ArrayList <POJO>使用Jackson

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

在我的测试客户端,我这样做,当然,因为有相关的类型不匹配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) } 

我知道我可以通过创建一个只有在它的ArrayList<MyPojo>“响应”对象缓解这个问题,但我将不得不为每一个类型我想回到创建这些有点无用之物。

我也在网上查看JacksonInFiveMinutes,但有一个可怕的时间了解有关Map<A,B>的东西,以及它如何与我的问题。如果你不能说,我完全不熟悉Java,并且来自Obj-C背景。他们特别提到:

除了结合POJO和“简单”类型外,还有一个额外的 变种:即结合通用(类型)的容器。 由于所谓的类型擦除 (由Java用于实现向后兼容的 方式的泛型),这种情况需要特殊处理,这可以防止您使用类似 Collection.class(不能编译)的东西。

所以,如果你想将数据绑定到一个地图,你将需要使用:

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

我怎么能直接反序列化ArrayList

回答

101

您可以使用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; 
} 

并且因此使用:

final String json = ""; 
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json); 

TypeReference Javadoc

+0

你的回答似乎与他们的信息如何使用内置的'TypeReference'支持 - 我只是不明白怎么办呢?请参阅上面就如何指导我的编辑使用泛型。 – 2012-03-22 20:04:14

+0

嗯,它是相关的。但这是生产中代码的一个片段。忘记你的mixin,只需使用我所展示的代码(但是用当前实际bean类的名称替换POJO)。 – Perception 2012-03-22 20:07:39

+0

您的代码已编译,但在尝试打印出关于“NullPointerException”的'arrayList.toString()'时出现运行时异常。我猜测这可能是因为我的POJO不符合其属性的正确命名约定,也就是说,整个问题是Web服务返回Prop1Member而我的对象有Prop1。这是我使用mixins开始的唯一真正原因,所以我不必将'@ JsonProperty'的声明放在我的纯对象中。 – 2012-03-22 20:19:03

3

我也有同样的问题。我有一个将被转换为ArrayList的json。

帐户看起来像这样。

Account{ 
    Person p ; 
    Related r ; 

} 

Person{ 
    String Name ; 
    Address a ; 
} 

以上所有类都已正确注释。 我试过TypeReference>(){} ,但不起作用。

它给了我Arraylist,但ArrayList有一个linkedHashMap,其中包含一些更多的包含最终值的链接hashmaps。

我的代码如下:

public T unmarshal(String responseXML,String c) 
{ 
    ObjectMapper mapper = new ObjectMapper(); 

    AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

    mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

    mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
    try 
    { 
     this.targetclass = (T) mapper.readValue(responseXML, new TypeReference<ArrayList<T>>() {}); 
    } 
    catch (JsonParseException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (JsonMappingException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    return this.targetclass; 
} 

我终于解决了这个问题。我可以列表直接转换成JSON字符串到的ArrayList如下:

JsonMarshallerUnmarshaller<T>{ 

    T targetClass ; 

    public ArrayList<T> unmarshal(String jsonString) 
    { 
     ObjectMapper mapper = new ObjectMapper(); 

     AnnotationIntrospector introspector = new JacksonAnnotationIntrospector(); 

     mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); 

     mapper.getSerializationConfig().withAnnotationIntrospector(introspector); 
     JavaType type = mapper.getTypeFactory(). 
        constructCollectionType(ArrayList.class, targetclass.getClass()) ; 
     try 
     { 
     Class c1 = this.targetclass.getClass() ; 
     Class c2 = this.targetclass1.getClass() ; 
      ArrayList<T> temp = (ArrayList<T>) mapper.readValue(jsonString, type); 
     return temp ; 
     } 
     catch (JsonParseException e) 
     { 
     e.printStackTrace(); 
     } 
     catch (JsonMappingException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    return null ; 
    } 

} 
48

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

ObjectMapper objectMapper = new ObjectMapper(); 
MyPojo[] pojos = objectMapper.readValue(json, MyPojo[].class); 

这样你避免所有的麻烦与类型的对象,如果你真的需要一个列表,你总是可以将数组转换为列表:

List<MyPojo> pojoList = Arrays.asList(pojos); 

恕我直言,这是更具可读性。

,并使其成为一个实际的列表(可以修改的,看到的Arrays.asList()限制),那么只要做到以下几点:

List<MyPojo> mcList = new ArrayList<>(Arrays.asList(pojos)); 
+2

这应该是被接受的答案,确实简单并且可读性更高。 – dic19 2017-01-12 20:18:54

+0

同意^这种方式更有帮助 – cstaikos 2017-07-06 15:18:09

7

这种变体看起来更加简洁大方。

CollectionType typeReference = 
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class); 
List<Dto> resultDto = objectMapper.readValue(content, typeReference); 
相关问题