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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9829403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 08:16:56  来源:igfitidea点击:

Deserialize JSON to ArrayList<POJO> using Hymanson

javajsonmappingHymanson

提问by tacos_tacos_tacos

I have a Java class MyPojothat I am interested in deserializing from JSON. I have configured a special MixIn class, MyPojoDeMixIn, to assist me with the deserialization. MyPojohas only intand Stringinstance variables combined with proper getters and setters. MyPojoDeMixInlooks something like this:

我有一个 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) {}
}

In my test client I do the following, but of course it does not work at compile time because there is a JsonMappingExceptionrelated 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.

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

I also looked online at HymansonInFiveMinutesbut had a terrible time understanding the stuff about Map<A,B>and how it relates to my issue. If you cannot tell, I'm entirely new to Java and come from an Obj-C background. They specifically mention:

我还在线查看了HymansonInFiveMinutes,但在理解与Map<A,B>我的问题有关的内容以及它与我的问题之间的关系时遇到了很糟糕的时间。如果您不知道,我对 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:

除了绑定到 POJO 和“简单”类型之外,还有一个额外的变体:绑定到泛型(类型化)容器。由于所谓的类型擦除(Java 用于以某种向后兼容的方式实现泛型),这种情况需要特殊处理,这会阻止您使用诸如 Collection.class(它不会编译)之类的东西。

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

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

How can I deserialize directly to ArrayList?

如何直接反序列化为ArrayList

采纳答案by Perception

You can deserialize directly to a list by using the TypeReferencewrapper. An example method:

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

And is used thus:

并且这样使用:

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

TypeReference Javadoc

类型参考 Javadoc

回答by rushidesai1

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 HymansonAnnotationIntrospector();

    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 HymansonAnnotationIntrospector();

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

}

回答by DevNG

Another way is to use an array as a type, e.g.:

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

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

回答by Дмитрий Кулешов

This variant looks more simple and elegant.

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

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

回答by Jugal Panchal

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