Sending JSON request bodies

7,898 views
Skip to first unread message

Emerson Farrugia

unread,
Feb 8, 2013, 9:26:22 AM2/8/13
to gat...@googlegroups.com
Hi,

I'm wondering if there's a simple way to marshall a Java/Scala object and send it as a POST or PUT request body. https://github.com/excilys/gatling/wiki/HTTP#wiki-request-body assumes that the requests are already in JSON format, either as Strings, or as request body files, or as SSPs, but it could be useful to marshall straight from a Java/Scala object.

Thanks,
Emerson 

Stéphane Landelle

unread,
Feb 8, 2013, 9:32:57 AM2/8/13
to gat...@googlegroups.com
Hi,

You can pass a function to byteArrayBody where you can call whatever marshaling engine call you want.
We'll probably enrich this feature in order to make things easier for non plain text formats such as BSON, protobuf or GWT-RPC.

However, I fail to see the point for JSON that's a plain text format. Could you explain, please?

Cheers,

Stéphane


2013/2/8 Emerson Farrugia <emerson....@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Gatling User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gatling+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Emerson Farrugia

unread,
Feb 8, 2013, 10:27:05 AM2/8/13
to gat...@googlegroups.com
Hi.

Thanks for the quick answer. I agree that using byteArrayBody isn't a good fit for a plain text format.

Sure, I can give some background. I've got a Java API exposed using Spring MVC, so my requests and responses are all defined as Java objects. In order to test this API with as little effort as possible, I'd like to use these Java clases from Scala, call their setters, and specify the object itself as the thing to marshall and send. For example, imagine some syntax like 

http("request").post("uri").objectBody(newObject(foo)).asJSON
where newObject builds the object to send, objectBody specifies the Scala/Java object, and asJSON does the serialization.

The two alternatives right now that I can see are to

1. Manually pass all my objects through Jackson to get their JSON equivalent, and copy the produced JSON to request body files. The problem here, besides the manual labour, is that those request body files would need to be maintained should the objects change. Using objects I could find usages when I modify the object and updated my Scala test code accordingly.
2. Use the standard body() call and replace newObject() with newObjectAsString(), which would somehow call Jackson to give me back a String representation of the passed object (not something I'm comfortable with just yet given how completely new I am to both Gatling and Scala)

Thoughts?

Thanks,
Emerson

Stéphane Landelle

unread,
Feb 8, 2013, 11:26:32 AM2/8/13
to gat...@googlegroups.com
Thanks for the quick answer. I agree that using byteArrayBody isn't a good fit for a plain text format.
That's not what I meant.
I meant that I don't see the point of going through all the marshaling hassle for a plain text format such as JSON. Going this way would be much more complex (marshaling code, shipping DTO classes) and less efficient that using a plain text template.
Note that you can also pass a body with body(Session => String)
 

Sure, I can give some background. I've got a Java API exposed using Spring MVC, so my requests and responses are all defined as Java objects. In order to test this API with as little effort as possible, I'd like to use these Java clases from Scala, call their setters, and specify the object itself as the thing to marshall and send. For example, imagine some syntax like 
http("request").post("uri").objectBody(newObject(foo)).asJSON 
where newObject builds the object to send, objectBody specifies the Scala/Java object, and asJSON does the serialization.

asJSON already exists, but it just sets the ContentType. Changing its responsibility would break the existing API.
You'd need a jsonBody that would do the serialization.
 

The two alternatives right now that I can see are to

1. Manually pass all my objects through Jackson to get their JSON equivalent, and copy the produced JSON to request body files. The problem here, besides the manual labour, is that those request body files would need to be maintained should the objects change. Using objects I could find usages when I modify the object and updated my Scala test code accordingly.

The manual labour can be reduced thanks to the recorder that can dump the raw file bodies for you. But yes, changing requests comes with a maintenance cost. Only a browser-like tool, like Selenium/webkit, would be able to reduce this cost, but it would ill fitted for stress testing (too CPU consuming, would need a 50 server cluster).
 
2. Use the standard body() call and replace newObject() with newObjectAsString(), which would somehow call Jackson to give me back a String representation of the passed object (not something I'm comfortable with just yet given how completely new I am to both Gatling and Scala)

And yet, if you really want to go that way, that's the way to go ;)
Learning Scala basics is not that hard, Twitter Scala School is a good starter.http://twitter.github.com/scala_school

So, you'd just have to write something like :

// There's already a Jackson ObjectMapper instance in Gatling that you can reuse
import com.excilys.ebi.gatling.core.check.extractor.jsonpath.JsonPathExtractor.mapper

.body(session =>
   // build your POJO with values from the session
   val myPOJO = ...
   mapper.writeValueAsString(myPOJO)
)

And that's it!

Cheers,

Stéphane

Emerson Farrugia

unread,
Feb 8, 2013, 11:50:25 AM2/8/13
to gat...@googlegroups.com
Thanks for all the info, really useful, and it'll hopefully be useful to whoever digs up this conversation down the line.

I'll try the SSP method to avoid the marshalling hit, and experiment with the ObjectMapper route if I have time. 

Cheers,
Emerson



--

dd...@twilio.com

unread,
Sep 26, 2013, 1:05:42 PM9/26/13
to gat...@googlegroups.com
Hi Stéphane & Emerson,
I am a new user of Gatling & Scala & I have some question related to sending Json strings as request bodies. 
Here is my problem:
I have a json file containing multiple json blobs, separated by newlines. 
I want to send as many as POSTs as there are entries in that Json file with different request bodies i.e each POST has one Json string from that Json file.

I could find body().asJson & fileBody().asJson. But the problem is fileBody() takes the contents of the entire Json file.

Can I do something like:
for(line : "myJsonfile.Json") {
http("String body").post("my.post.uri")
  .body(${line}).asJSON
...
}

So not sure how to achieve the above scenario.

Thanks,
Debasis

Stéphane Landelle

unread,
Sep 26, 2013, 2:22:09 PM9/26/13
to gat...@googlegroups.com
Hi,

So you have one json object per line, right?
Which version of Gatling do you use?

Stéphane


2013/9/26 <dd...@twilio.com>

dd...@twilio.com

unread,
Sep 26, 2013, 4:18:00 PM9/26/13
to gat...@googlegroups.com
Hi Stéphane, thanks for the response.

I am using 1.5.2.

Also I tried to do something like putting the json blobs in a single column tsv/ssv file & use feed() & body().asJSON to populate the body of the POST. But Looks like the resultant JSON in the POST is malformed. Specifically wherever there is a blank value i.e "myValue":"" then it truncates the double "" to one ". And also one more scenario is:

{"t":"voipmonitor", ... is truncated to  {t":"voipmonitor", ... The {"t" is truncated to {t" . 

Is there something wrong I am doing here?


The exact Json blob is:

{"t":"monitor", "source":"monitor", "caller":"+176", "callername":"+76976", "callerip":"x.x.x.x", "sippcalledip":"x.x.x.x", "called":"+76", "duration":12, "progress_time":2, "first_rtp_time":2, "connect_duration":3, "calltimestamp":1380052560, "fbasename":"669eb3180fa52f64103698c665d31419@c.c.c.c", "hostsid":"ade4f70a78f5b3ff123be73", "oname":"606258145d5dd6c3c", "callsegmentsid":"", "s_dt":"s3:\/\/com.twilio.dev.logs\/hurl\/2013-09-24\/669eb3180fa52f64103698c665d31419@16ade4f70a78f5b3ff123be73.ap", "call_id":"", "client":"", "roles":"url", "s_region":"dev", "availability_zone":"us-1d", "providerd":"fe7861f564cec468cf20132222", "accountsid":"8e2339cc04ba82dac696e", "sighup":0, "lastresponse":"0 OK", "lastum":200, "bye":3, "anged":"callee", "a_ua":"", "b_ua":"risk PX", "a_index":0, "a_received":511, "a_lost":0, "a_avgjitter":0.136228, "a_maxjitter":0.867274, "a_payload":0, "a_sl1":0, "a_sl2":0, "a_sl3":0, "a_sl4":0, "a_sl5":0, "a_sl6":0, "a_sl7":0, "a_sl8":0, "a_sl9":0, "a_sl10":0, "a_d50":0, "a_d70":0, "a_d90":0, "a_d120":0, "a_d150":0, "a_d200":0, "a_d300":0, "a_saddr":"208.93.226.14", "a_lossr_f1":0, "a_burstr_f1":0, "a_mos_f1":4.5, "a_lossr_f2":0, "a_burstr_f2":0, "a_mos_f2":4.5, "a_lossr_adapt":0, "a_burstr_adapt":0, "a_mos_adapt":4.5, "b_index":0, "b_received":511, "b_lost":0, "b_avgjitter":0.136228, "b_maxjitter":0.867274, "b_payload":0, "b_sl1":0, "b_sl2":0, "b_sl3":0, "b_sl4":0, "b_sl5":0, "b_sl6":0, "b_sl7":0, "b_sl8":0, "b_sl9":0, "b_sl10":0, "b_d50":0, "b_d70":0, "b_d90":0, "b_d120":0, "b_d150":0, "b_d200":0, "b_d300":0, "b_saddr":"208.93.226.14", "b_lossr_f1":0, "b_burstr_f1":0, "b_mos_f1":4.5, "b_lossr_f2":0, "b_burstr_f2":0, "b_mos_f2":4.5, "b_lossr_adapt":0, "b_burstr_adapt":0, "b_mos_adapt":4.5}  

Narayanan K

unread,
Aug 30, 2015, 11:11:08 PM8/30/15
to Gatling User Group
Hi

Was any solution prescribed for the above scenario for POSTing a URL using one json message body per line from a file ?

Thanks
Narayanan
Reply all
Reply to author
Forward
0 new messages