关于java:使用Jackson将JSON反序列化为ArrayList

Deserialize JSON to ArrayList using Jackson

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

1
2
3
4
5
6
public abstract class MyPojoDeMixIn {
  MyPojoDeMixIn(
      @JsonProperty("JsonName1") int prop1,
      @JsonProperty("JsonName2") int prop2,
      @JsonProperty("JsonName3") String prop3) {}
}

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

1
2
3
4
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的"Response"对象来缓解这个问题,但是我必须为我想要返回的每个类型创建这些有些无用的对象。

我也在网上看过JacksonInFiveMinutes,但是很难理解Map的内容以及它与我的问题有什么关系。 如果你不能说,我是Java的新手,来自Obj-C背景。 他们特别提到:

In addition to binding to POJOs and"simple" types, there is one
additional variant: that of binding to generic (typed) containers.
This case requires special handling due to so-called Type Erasure
(used by Java to implement generics in somewhat backwards compatible
way), which prevents you from using something like
Collection.class (which does not compile).

So if you want to bind data into a Map you will need to use:

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

如何直接反序列化为ArrayList


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

1
2
3
4
5
6
7
8
9
10
11
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;
}

因此使用:

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

TypeReference Javadoc


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

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

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

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

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

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

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


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

1
2
3
CollectionType typeReference =
    TypeFactory.defaultInstance().constructCollectionType(List.class, Dto.class);
List<Dto> resultDto = objectMapper.readValue(content, typeReference);

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

帐户看起来像这样。

1
2
3
4
5
6
7
8
9
10
Account{
  Person p ;
  Related r ;

}

Person{
    String Name ;
    Address a ;
}

所有上述类都已正确注释。
我试过TypeReference>(){}
但是没有用。

它给了我Arraylist但是ArrayList有一个linkedHashMap,它包含一些包含最终值的链接哈希映射。

我的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 String中的List直接转换为ArrayList,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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 ;
    }  

}

这适合我。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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.
}