【问题标题】:Deserialize JSON to ArrayList<POJO> using Jackson使用 Jackson 将 JSON 反序列化为 ArrayList<POJO>
【发布时间】:2012-04-07 10:26:03
【问题描述】:

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

在我的测试客户端中,我执行以下操作,但它当然在编译时不起作用,因为存在与类型不匹配相关的 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&lt;MyPojo&gt; 的“响应”对象来缓解这个问题,但是我必须为我想要返回的每种类型创建这些有点无用的对象。

我也在网上查看了JacksonInFiveMinutes,但很难理解有关Map&lt;A,B&gt; 的内容以及它与我的问题的关系。如果你不知道,我对 Java 完全陌生,并且来自 Obj-C 背景。他们特别提到:

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

因此,如果您想将数据绑定到地图中,您需要使用:

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

如何直接反序列化为ArrayList

【问题讨论】:

标签: java json mapping jackson


【解决方案1】:

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

【讨论】:

  • 您的回答似乎与他们有关如何使用对TypeReference 的内置支持的信息有关-我只是不知道该怎么做...请参阅我上面的编辑以获取他们的说明关于如何使用泛型。
  • 嗯,这是相关的。但这是生产中工作代码的 sn-p。忘记你的 mixin,只需使用我展示的代码(当然,用你的实际 bean 类的名称替换 POJO)。
  • 您的代码已编译,但在尝试打印关于 NullPointerExceptionarrayList.toString() 时出现运行时异常。我猜这可能是因为我的POJO 不符合其属性的正确命名约定,也就是说,整个问题是Web 服务返回Prop1Member 而我的对象有Prop1。这是我开始使用 mixins 的唯一真正原因,因此我不必将 @JsonProperty 的声明放在我的纯对象中。
  • 目视检查您的阵列以确保您至少获得了一个列表。如果需要添加 mixin,它应该与 TypeReference 一起工作以使所有内容都整齐地反序列化。
  • @JsonProperty 并不像人们想象的那么邪恶。很难摆脱供应商特定的注释,因为该领域的当前标准化状态(最低限度)。
【解决方案2】:

这对我有用。

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

【讨论】:

    【解决方案3】:

    这个变种看起来更简洁优雅。

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

    【讨论】:

    • 感谢明确的CollectionType 参考。
    【解决方案4】:

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

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

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

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

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

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

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

    【讨论】:

    • 优雅肯定,但由于 MyPojo[].class ,我无法将其泛化,我不想将其作为参数传递。
    • 我认为使用TypeFactory 如下一个答案所述:stackoverflow.com/a/42458104/91497 是杰克逊指定类型的方式。
    【解决方案5】:

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

    帐户如下所示。

    Account{
      Person p ;
      Related r ;
    
    }
    
    Person{
        String Name ;
        Address a ;
    }
    

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

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

    我的代码如下:

    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,如下所示:

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

    【讨论】:

      猜你喜欢
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-08
      • 2020-12-10
      • 2014-10-22
      • 1970-01-01
      • 2017-08-09
      相关资源
      最近更新 更多