【问题标题】:Rest Assured - deserialize Response JSON as List<POJO>放心 - 将响应 JSON 反序列化为 List<POJO>
【发布时间】:2014-03-10 14:39:42
【问题描述】:

我有一个 POJO Artwork。我正在从 JSON 格式的 HTTP 响应正文中的 RESTful Web 服务中检索这些对象的 List。我正在尝试编写一个基于 Rest Assured 的测试来分析返回的列表。代码如下所示:

Response response = get("/artwork");
List returnedArtworks = response.getBody().as(List.class)

问题是,我无法让 Rest Assured 将返回的 JSON 解析为 List&lt;Artwork&gt;。相反,我得到了List&lt;LinkedHashMap&gt;。该地图具有适当的结构,即可以由 Jackson 映射到 Artwork 对象,但我想避免手动映射它。

我的模型中的 JSON 映射是可以的,因为当我像这样映射单个对象时:

Artwork returnedArtwork = response.getBody().as(Artwork.class);

效果很好。

是否可以将returnedArtworks 设为List&lt;Artwork&gt;

【问题讨论】:

  • 在下面回答了你的问题..

标签: java json generics rest-assured


【解决方案1】:

请放心,在问题中使用 Class 的版本旁边提供 as(java.lang.reflect.Type)

java.lang.reflect.Type type; //TODO defines the type.
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)

在我看来,type 变量的方式取决于所使用的序列化库。


如果使用 Gson,正如Purushotham's answer 所指出的,可以使用TypeToken。我更喜欢直接放心使用:

Type type = new TypeToken<List<Artwork>>(){}.getType();
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)

在使用 Jackson 时,解决方案是使用TypeFactoryjavadocsource)来告诉它应该反序列化为哪种类型:

Type type = TypeFactory.defaultInstance().constructCollectionLikeType(ArrayList.class, Artwork.class);
Response response = get("/artwork");
List<Artwork> returnedArtworks = response.getBody().as(type)

【讨论】:

    【解决方案2】:

    使用 REST 保证 3.0.2,您可以简单地检查数组中是否存在内容

    when().get("/artwork").then().body("artworks", hasItem("some art");
    //or check multiple values in array
    when().get("/artwork").then().body("artworks", hasItems("some art", "other art");
    

    通过这种方式,您将通过转换 JSON 来避免代码的复杂性,以列出更多如何检查响应内容的示例可以找到 link

    【讨论】:

      【解决方案3】:

      此解决方案适用于版本 3.0.2 (io.restassured):

        JsonPath jsonPath = RestAssured.given()
           .when()
           .get("/order")
           .then()
           .assertThat()
           .statusCode(Response.Status.OK.getStatusCode())
           .assertThat()
           .extract().body().jsonPath();
      
        List<Order> orders = jsonPath.getList("", Order.class);
      

      这将为这样的结构提取对象:

      public class Order {
      
      private String id;
      
      public String getId(){
      return id; }
      
      public void setId(String id){
      this.id = id;
      }
      
      
      }
      

      使用给定的 json:

      [ 
      { "id" : "5" }, 
      { "id" : "6" }
      ]
      

      【讨论】:

        【解决方案4】:

        你可以这样做:

        List<Artwork> returnedArtworks = Arrays.asList(response.getBody().as(Artwork[].class));
        

        诀窍是将JSON反序列化为对象数组(因为数组和列表的JSON字符串没有区别),然后将数组转换为列表。

        【讨论】:

        • 您应该为找到此问题的其他人添加解决方案的说明。
        • 谢谢,我添加了一个简短的解释(并更正了一个错误)。
        • 现在无法检查,但假设所有赞成票都来自发现此解决方案有用的用户,我将其标记为已接受的答案
        • 我赞成这个答案,因为它很简洁。但这对我不起作用。我花了两个小时试图修复它,虽然我得到了这个错误:com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of .................
        【解决方案5】:

        通过使用 Google 的 Gson 库,您可以轻松地将其解析为 List&lt;Artwork&gt;。试试下面的代码

        Gson gson = new Gson();
        List<Artwork> returnedArtworks = gson.fromJson(jsonStr, new TypeToken<List<Artwork>>(){}.getType());
        
        //* where jsonStr is the response string(Json) receiving from your Restful webservice
        

        【讨论】:

        • 感谢您的回答。不过,这正是我想要避免的:“地图具有适当的结构,即可以由 Jackson 映射到 Artwork 对象,但我想避免手动映射它。”我在想是否有机会或多或少像这样:List&lt;Artwork&gt; returnedArtworks = response.getBody().asListOf(Artwork.class)
        • 如果您的 Artwork 类与您从响应中收到的地图完全匹配,您可以使用 Gson 而不是 Jackson。您可以重复使用相同的 Artwork 类。
        • 我使用 Gson 还是 Jackson 并不重要。无论哪种情况,我都必须编写额外的代码行来解析响应中收到的地图。我希望 Rest Assured 能以某种方式实现它,因为我们经常收到 List 的对象作为响应。
        • TypeToken#getType() 可以直接用作放心.as() 中的参数。看我的回答:stackoverflow.com/a/57373937/91497
        猜你喜欢
        • 2017-08-09
        • 2022-08-04
        • 2018-10-06
        • 1970-01-01
        • 2021-06-14
        • 2015-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多