Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rest Assured: extract value from Response List

I have a List returned as response. I need to get one item from list using product.name and tariffPlan.name.

    [
  {
    "id": 123,
    "product": {
      "id": 1,
      "code": "credit",
      "name": "Credit"
    },
    "tariffPlan": {
      "id": 1,
      "code": "gold",
      "name": "Gold"
    }
  },
  {
    "id": 234,
    "product": {
      "id": 2,
      "code": "debit",
      "name": "Debit"
    },
    "tariffPlan": {
      "id": 1,
      "code": "gold",
      "name": "Gold"
    }
  }
]

I use Java8. Here is my method. I got List of Card.class elements. And then I need to get single Item from list with specified "product.name" and "tariffPlan.name".

public List<Card> getCardId(String productName, String tariffPlanName) {
    return given()
        .param("product.name", productName)
        .param("tariffPlan.name", tariffPlanName)
        .when().get("/").then()
        .extract().jsonPath().getList("", Card.class);
  }

Is it possible to do it with restAssured? Maybe use .param method like in my example? But in my example .param method is ignored. Thank you for your ideas.

UPD. My decision is:

 public Card getCard(String productName, String tariffPlanName) {
    List<Card> cardList = given()
        .when().get("/").then()
        .extract().jsonPath().getList("", Card.class);

    return cardList.stream()
        .filter(card -> card.product.name.equals(productName))
        .filter(card -> card.tariffPlan.name.equals(tariffPlanName))
        .findFirst()
        .get();
  }
like image 826
Антон Avatar asked Oct 15 '25 14:10

Антон


2 Answers

If you need to get a value from response json list, here's what worked for me:

Json sample:
[
  {
    "first": "one",
    "second": "two",
    "third": "three"
  }
]

Code:

String first =
given
  .contentType(ContentType.JSON)
.when()
  .get("url")
.then()
.extract().response().body().path("[0].first")
like image 58
Sofia Temnyk Avatar answered Oct 17 '25 02:10

Sofia Temnyk


Actually, you can but... you need to handle deserialization issue of default mapper becase if you try do the following:

.extract().jsonPath().getList("findAll {it.productName == " + productName + "}", Card.class);

You will failing on converting HashMap to your object type. It happens because of using gpath expression in path provides json without double quotes on keys by default. So you need to prettify it with (you can put it in RestAssured defaults):

.extract().jsonPath().using((GsonObjectMapperFactory) (aClass, s) -> new GsonBuilder().setPrettyPrinting().create())

And as result your would be able to cast things like that:

.getObject("findAll {it.productName == 'productName'}.find {it.tariffPlanName.contains('tariffPlanName')}", Card.class)

See full example:

import com.google.gson.GsonBuilder;
import io.restassured.http.ContentType;
import io.restassured.mapper.factory.GsonObjectMapperFactory;
import lombok.Data;
import org.testng.annotations.Test;

import java.util.HashMap;
import java.util.List;

import static io.restassured.RestAssured.given;

public class TestLogging {

    @Test
    public void apiTest(){
        List<Item> list = given()
                .contentType(ContentType.JSON)
                .when()
                .get("https://jsonplaceholder.typicode.com/posts")
                .then().log().all()
                .extract().jsonPath().using((GsonObjectMapperFactory) (aClass, s) -> new GsonBuilder().setPrettyPrinting().create())
                .getList("findAll {it.userId == 6}.findAll {it.title.contains('sit')}", Item.class);
        list.forEach(System.out::println);
    }

    @Data
    class Item {
        private String userId;
        private String id;
        private String title;
        private String body;
    }
}
like image 23
RocketRaccoon Avatar answered Oct 17 '25 03:10

RocketRaccoon