REST Assured - Generic List deserialization
JavaArraysJsonDeserializationRest AssuredJava Problem Overview
Let's say I have a Java Person
class:
class Person {
String name;
String email;
}
With REST Assured, you can deserialize this JSON object
{"name":"Bob", "email":"[email protected]"}
to a Java Person
instance using
Person bob = given().when().get("person/Bob/").as(Person.class);
How does one use REST Assured to deserialize this JSON array
[{"name":"Bob", "email":"[email protected]"},
{"name":"Alice", "email":"[email protected]"},
{"name":"Jay", "email":"[email protected]"}]
into a List<Person>
? For example, this would be handy:
List<Person> persons = given().when().get("person/").as(...);
Java Solutions
Solution 1 - Java
I found a way to achieve what I wanted:
List<Person> persons = given().when().get("person/").as(Person[].class);
UPDATE: Using Rest-Assured 1.8.1, looks like cast to List is not supported anymore. You need to declare and object array like this:
Person[] persons = given().when().get("person/").as(Person[].class);
Solution 2 - Java
To extract a Java List, and not an Array, from a JSON API response, you just have to remember to use jsonPath
rather than as
:
List<Person> persons = given()
.when()
.get("/person")
.then()
.extract()
.body()
// here's the magic
.jsonPath().getList(".", Person.class);
Your json path can point to anywhere you expect to have a list of json objects in your body. in this example (and working for your question) it just points to the json root.
sidenode: rest-assured is internally using jackson for deserialization (for .jsonPath
as well as .as
)
Solution 3 - Java
for those who found out that accepted answer does not work anymore.
List<Entity> list = new ArrayList<>();
list = given()
.contentType(CONTENT_TYPE)
.when()
.get(getRestOperationPath())
.then()
.extract().body().as(list.getClass());
hopefully, you understand that getRestOperationPath is returning rest operation path; and CONTENT_TYPE is placeholder for your content type (application/json for example)
upd: checked different versions, behavior differs depending on version, so you might want to try different approaches
upd2: cleaner solution was pointed by @Arigion in comments:
to use .extract().body().jsonPath().getList(".", Entity.class);
Solution 4 - Java
You could also do this if you were interested in using "expect()"
expect().
body("get(0).firstName", equalTo("Mike")).
when().
get("person/");
This was my case
Solution 5 - Java
We can now use TypeRef
much as it's possible to do it with the JsonPath library:
List<Person> persons = given().when().get("person/")
.as(new TypeRef<List<Person>>() {});
As with https://github.com/json-path/JsonPath#what-is-returned-when - the anonymous inner class new TypeRef<List<Person>>() {}
gets around type erasure and captures the type information enough that the framework can access the raw type - List
in this case. The internal generic type - Person
- is a safe cast that can be made under the circumstances.
Solution 6 - Java
If anyone's still looking. Using Java 1.8 and RestAssured 2.9 the solution is really simple and it does not throw "Unchecked Warning".
return Arrays.asList(given()
.when()
.get("restPath")
.then()
.extract()
.response()
.body()
.as(Player[].class));
Solution 7 - Java
If you are not comfortable with JsonPath, i would suggest using any java serialization/de-serialization using GSON or Jackson.
Solution 8 - Java
This would be helpful, works with current version of 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);
}
Solution 9 - Java
Since you want to map
[{"name":"Bob", "email":"[email protected]"},
{"name":"Alice", "email":"[email protected]"},
{"name":"Jay", "email":"[email protected]"}]
to java object.
Now while calling the endpoint you can directly map to the Person list as shown below
List<Person> personList = given().when().get("person/").as(Person[].class);
Note the Person class should remain same i.e. no need to do any modification for the person class.
public class Person{
String name;
String email;
}