简体   繁体   English

将 JSON 反序列化为 ArrayList<POJO> 使用杰克逊

[英]Deserialize JSON to ArrayList<POJO> using Jackson

I have a Java class MyPojo that I am interested in deserializing from JSON.我有一个我对从 JSON 反序列化感兴趣的 Java 类MyPojo I have configured a special MixIn class, MyPojoDeMixIn , to assist me with the deserialization.我配置了一个特殊的 MixIn 类MyPojoDeMixIn来帮助我进行反序列化。 MyPojo has only int and String instance variables combined with proper getters and setters. MyPojo只有intString实例变量以及适当的 getter 和 setter。 MyPojoDeMixIn looks something like this: MyPojoDeMixIn看起来像这样:

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

In my test client I do the following, but of course it does not work at compile time because there is a JsonMappingException related to a type mismatch.在我的测试客户端中,我执行以下操作,但它当然在编译时不起作用,因为存在与类型不匹配相关的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) }

I am aware that I could alleviate this issue by creating a "Response" object that has only an ArrayList<MyPojo> in it, but then I would have to create these somewhat useless objects for every single type I want to return.我知道我可以通过创建一个只有一个ArrayList<MyPojo>的“响应”对象来缓解这个问题,但是我必须为我想要返回的每种类型创建这些有点无用的对象。

I also looked online at JacksonInFiveMinutes but had a terrible time understanding the stuff about Map<A,B> and how it relates to my issue.我还在网上查看了JacksonInFiveMinutes ,但在理解有关Map<A,B>的内容以及它与我的问题之间的关系时遇到了可怕的事情。 If you cannot tell, I'm entirely new to Java and come from an Obj-C background.如果你不知道,我对 Java 完全陌生,并且来自 Obj-C 背景。 They specifically mention:他们特别提到:

In addition to binding to POJOs and "simple" types, there is one additional variant: that of binding to generic (typed) containers.除了绑定到 POJO 和“简单”类型之外,还有一个额外的变体:绑定到通用(类型化)容器。 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).由于所谓的类型擦除(Java 使用它以某种向后兼容的方式实现泛型),这种情况需要特殊处理,这会阻止您使用诸如 Collection.class 之类的东西(它不会编译)。

So if you want to bind data into a Map you will need to use:因此,如果要将数据绑定到 Map 中,则需要使用:

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

How can I deserialize directly to ArrayList ?如何直接反序列化为ArrayList

You can deserialize directly to a list by using the TypeReference wrapper.您可以使用TypeReference包装器直接反序列化为列表。 An example method:一个示例方法:

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;
}

And is used thus:并因此使用:

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

TypeReference Javadoc 类型参考 Javadoc

Another way is to use an array as a type, eg:另一种方法是使用数组作为类型,例如:

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

This way you avoid all the hassle with the Type object, and if you really need a list you can always convert the array to a list by:这样你就避免了 Type 对象的所有麻烦,如果你真的需要一个列表,你总是可以通过以下方式将数组转换为列表:

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

IMHO this is much more readable.恕我直言,这更具可读性。

And to make it be an actual list (that can be modified, see limitations of Arrays.asList() ) then just do the following:并使其成为一个实际列表(可以修改,请参阅Arrays.asList()的限制),然后执行以下操作:

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

This variant looks more simple and elegant.这种变体看起来更简单优雅。

//import com.fasterxml.jackson.core.JsonProcessingException;
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.databind.type.CollectionType;
//import com.fasterxml.jackson.databind.type.TypeFactory;

//import java.util.List;


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

I am also having the same problem.我也有同样的问题。 I have a json which is to be converted to ArrayList.我有一个要转换为 ArrayList 的 json。

Account looks like this.帐户看起来像这样。

Account{
  Person p ;
  Related r ;

}

Person{
    String Name ;
    Address a ;
}

All of the above classes have been annotated properly.以上所有类都已正确注释。 I have tried TypeReference>() {} but is not working.我试过 TypeReference>() {} 但没有用。

It gives me Arraylist but ArrayList has a linkedHashMap which contains some more linked hashmaps containing final values.它给了我 Arraylist 但 ArrayList 有一个linkedHashMap,其中包含更多包含最终值的链接哈希图。

My code is as Follows:我的代码如下:

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;
}

I finally solved the problem.我终于解决了这个问题。 I am able to convert the List in Json String directly to ArrayList as follows:我可以将 Json String 中的 List 直接转换为 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 ;
    }  

}

This works for me.这对我有用。

@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.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM