Get data from json response array

Hi,

I’m working on Web Services who return data in JSON.
Many of them returning data this way (simplify for the example):

{
“items”: [
{
“id”: “123”,
“name”: “test”
},
{
“id”: “456”,
“name”: “other”
}
],
“pagingInfos”: {}
}

I cannot know how many items it will have in items array, I want to get one random item from this array, then get is “id” for use it in another Web Service.

I found this in a previous post: https://gist.github.com/slandelle/2469375
But I don’t succeed to change it for my conveniance, specially on the cast part. I got that for the moment:

val getAll = exec(http(“Get one random friend”)
.get("/users/${user_id}/friendships")
.header(“Authorization”, “Bearer ${access_token}”)
.check(status.is(200), jsonPath("$.items").findAll.saveAs(“user_friends”)))
.exec((session: Session) => {
val friends = session(“user_friends”).as[List[String]]
session.set(“random_friend”, friends(math.max(random.nextInt(friends.length), 9)))
})

The exception on the line “as[List[String]]”:

java.lang.ClassCastException: scala.collection.immutable.Vector cannot be cast to scala.collection.immutable.List
at yelago.ws.GetUserFriendships$$anonfun$1.apply(GetUserFriendships.scala:22) ~[na:na]
at yelago.ws.GetUserFriendships$$anonfun$1.apply(GetUserFriendships.scala:21) ~[na:na]
at io.gatling.core.action.SessionHook.executeOrFail(SessionHook.scala:35) ~[gatling-core-2.0.0-SNAPSHOT.jar:2.0.0-SNAPSHOT]
at io.gatling.core.action.Failable$class.execute(Actions.scala:97) ~[gatling-core-2.0.0-SNAPSHOT.jar:2.0.0-SNAPSHOT]
at io.gatling.core.action.SessionHook.execute(SessionHook.scala:28) ~[gatling-core-2.0.0-SNAPSHOT.jar:2.0.0-SNAPSHOT]
at io.gatling.core.action.Action$$anonfun$receive$1.applyOrElse(Actions.scala:30) ~[gatling-core-2.0.0-SNAPSHOT.jar:2.0.0-SNAPSHOT]

Any help ? :slight_smile: Thanx !

Well, a Vector is simply not a List :wink:
Seq would be fine.

But then, Gatling EL has a random() builtin

You can use “${user_friends.random()}”

Humm that random method in EL will be great if I make it work.

I have this first scenario:

val getAll = exec(http(“Get all friends”)
.get(“/users/${user_id}/friendships”)
.header(“Authorization”, “Bearer ${access_token}”)
.check(status.is(200), jsonPath(“$.items”).findAll.saveAs(“user_friends”))
)

Follow by this second:

val getOneRandomFriend = exec(http(“Get one random friend”)
.get(“/users/${user_friends.random().id}”)
.header(“Authorization”, “Bearer ${access_token}”)
.check(status.is(200))
)

But got [ERROR] i.g.h.a.HttpRequestAction - No attribute named ‘user_friends.random().id’ is defined
Same error when I only put ${user_friends.random()}

No, “${user_friends.random().id}” is invalid

Only “${user_friends.random()}” is

No, “${user_friends.random().id}” is invalid

Only “${user_friends.random()}” is

The random() EL method not working either (maybe because user_friends was not consider as list ? I don’t know)

Finally I end up using an external library call Dijon (GitHub - jvican/dijon: A Dynamically Typed Scala Json Library) which allow me to treat my JSON response as an object.

Thanx anyway :slight_smile:

jsonPath("$.items")

Why do you capture the whole object while you only need the id: jsonPath("$.items.id"), otherwise, as you wrote it, you’re capturing the full object String.

Because as I say in the first post my json response is more complex and I cannot just use a jsonPath to fill my need.

In both cases, you only want all the ids, not the full objects.
What to do them them, either pick one randomly, or concat, comes in a second time.

capture: jsonPath("$.items.id").findAll.saveAs(“itemIds”)
random: “${itemIds.random}”
concat: session => session(“itemIds”).validate[Seq[String]].map(_.mkString(",")) // or whatever, I don’t know how you want to concat

If you really want the objects: jsonPath("$.items").as[Map[String, Any]]

Don’t use another parser. In terms of performance, you’ll shoot yourself in the foot!