REST Assured - 通用列表反序列化

65

假设我有一个Java的 Person 类:

class Person {
    String name;
    String email;
}

使用REST Assured,您可以反序列化此JSON对象

{"name":"Bob", "email":"bob@email.com"} 

使用Java Person实例

Person bob = given().when().get("person/Bob/").as(Person.class);

如何使用REST Assured反序列化这个JSON数组

[{"name":"Bob", "email":"bob@email.com"}, 
 {"name":"Alice", "email":"alice@email.com"}, 
 {"name":"Jay", "email":"jay@email.com"}]

如何将其转换为List<Person>?例如,这将非常方便:

List<Person> persons = given().when().get("person/").as(...);
9个回答

77
我找到了实现我想要的方法:
List<Person> persons = given().when().get("person/").as(Person[].class);

更新:使用 Rest-Assured 1.8.1,似乎不再支持将数据转换为 List。您需要像这样声明一个对象数组:

Person[] persons = given().when().get("person/").as(Person[].class);

对我来说没有用,出现了java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.introspect.AnnotatedMethod.getParameterType(I)错误。这个东西有什么前提条件吗? - Andrii Plotnikov
1
它对我来说完美地工作。我正在使用 https://mvnrepository.com/artifact/io.rest-assured/rest-assured/3.0.1 - Ramu
我的版本是2.4.1,所以可能是这个原因。 - Andrii Plotnikov

33

从JSON API响应中提取Java列表,而不是数组,您只需要记得使用 jsonPath 而不是 as :

从JSON API响应中提取Java List,而不是数组,您只需记住使用jsonPath而不是as

List<Person> persons = given()
        .when()
        .get("/person")
        .then()
        .extract()
        .body()
        // here's the magic
        .jsonPath().getList(".", Person.class);

你的JSON路径可以指向你期望在请求体中有JSON对象列表的任何位置。在这个例子中(并且适用于你的问题),它只是指向了JSON根节点。

旁注:rest-assured在内部使用Jackson进行反序列化(对于 .jsonPath 和 .as)


28

针对那些发现已被接受的答案不再起作用的人。

    List<Entity> list = new ArrayList<>();
    list = given()
            .contentType(CONTENT_TYPE)
        .when()
            .get(getRestOperationPath())
        .then()
            .extract().body().as(list.getClass());

希望您能明白,getRestOperationPath返回REST操作路径;而CONTENT_TYPE是您内容类型的占位符(例如application/json)

更新:经检查不同版本的行为有所不同,因此您可能需要尝试不同的方法

更新2:@Arigion在评论中提出了更加简洁的解决方案:

to use .extract().body().jsonPath().getList(".", Entity.class);

2
这应该是正确的答案。简洁,简单,也是最新的回答。 - Ryan Cox
6
否则会产生未经检查的警告,最好使用.extract().body().jsonPath().getList(".", Entity.class)。 - Arigion
@Arigion已经将其包含在答案中了 :) 请告诉我您是否已经使用该答案,以便我可以链接它;我没有找到它。 - Andrii Plotnikov

19

我们现在可以像使用JsonPath库一样使用TypeRef

List<Person> persons = given().when().get("person/")
    .as(new TypeRef<List<Person>>() {});
https://github.com/json-path/JsonPath#what-is-returned-when一样,匿名内部类new TypeRef<List<Person>>()绕过了类型擦除并捕获了足够的类型信息以使框架能够访问原始类型 - 在这种情况下是List。内部泛型类型Person是在特定情况下可以安全转换的内容。

2
更短的语法对我也非常有效:.as(new TypeRef<>() {}),感谢import io.restassured.mapper.TypeRef;,即使使用旧的2019 'io.rest-assured', version: '3.3.0'版本。 - MarkHu
@MarkHu 那很好! - Ashley Frieze

13

如果您有兴趣使用 "expect()",也可以这样做。

expect().
 body("get(0).firstName", equalTo("Mike")).
when().
 get("person/");
这是我的案例。

1
谢谢。"get(0)" 就是我需要的。 - asmaier

8

如果还有人在寻找此问题的解决方案。 使用Java 1.8和RestAssured 2.9 解决方案非常简单,并且不会抛出"Unchecked Warning"。

return Arrays.asList(given()
            .when()
            .get("restPath")
            .then()
            .extract()
            .response()
            .body()
            .as(Player[].class));

0

如果您对JsonPath不熟悉,我建议使用任何使用GSON或Jackson进行Java序列化/反序列化的方法。


-1

由于您想要进行映射

[{"name":"Bob", "email":"bob@email.com"}, 
 {"name":"Alice", "email":"alice@email.com"}, 
 {"name":"Jay", "email":"jay@email.com"}]

转换为Java对象。

现在,在调用端点时,您可以直接将其映射到如下所示的Person列表

List<Person> personList = given().when().get("person/").as(Person[].class);

请注意,Person类应该保持不变,即不需要对Person类进行任何修改。
public class Person{
 String name;
 String email;
}

类型 PersonArray 具有一个名为 personList 的 _字段_,该字段在上述数据中不存在。 - Ashley Frieze
@AshleyFrieze 感谢您的评论,我已经添加了额外的包装器。我已经修改了我的解决方案。 - Vikas Kumar

-2

这将是有帮助的,可以与当前版本的Rest Assured一起使用。

@Test
    public void apostUser() {
        Map<String,String> user = new HashMap<>();
        user.put("User_Id", "xyx1111");
        user.put("First_Name", "KS");
        user.put("Designation", "DR");

        given()
        .contentType("application/json")
        .body(user)
        .when().post("URI").then()
        .statusCode(200);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接