简体   繁体   中英

Rest Assured - deserialize Response JSON as List<POJO>

I have a POJO Artwork . I'm retrieving a List of those objects from a RESTful webservice in the HTTP response body in JSON format. I'm trying to write a Rest Assured-based test that would analyze the returned list. The code looks like this:

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

The problem is, I can't get Rest Assured to parse the returned JSON as List<Artwork> . Instead, I get a List<LinkedHashMap> . The map has a proper structure, ie could be mapped by Jackson to Artwork object, but I'd like to avoid mapping it manually.

JSON mappings in my model are OK, because when I map single object like this:

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

it works fine.

Is it possible to get returnedArtworks as List<Artwork> ?

You can do this:

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

The trick is to deserialize JSON to an array of objects (because there is no difference between the JSON string of an array or a list), then convert the array to a list.

this solution works for version 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);

This will extract the objects for a structure like this:

public class Order {

private String id;

public String getId(){
return id; }

public void setId(String id){
this.id = id;
}


}

with the given json:

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

By using Google's Gson library you can easily parse it to List<Artwork> . Try below code

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

With REST assured 3.0.2 you can simply check if content exists in the array

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

This way you will avoid complexity in your code by converting JSON to list more examples how to check response content can be found link

Rest-assured provide an as(java.lang.reflect.Type) next to the version expecting a Class used in the question.

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

In my opinion the way the type variable depends from the serialization lib that is used.


If using Gson, as pointed out by Purushotham's answer , TypeToken can be used. I prefer using it directly in rest-assured:

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

When using Jackson, the solution is to use the TypeFactory ( javadoc , source ) to tell to which type it should be de-serialized:

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

Here is a very good article written on how to deserialize the API response in POJO and validate further.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM