I have a nested JSON returned from an API that I am hitting using a GET request, in POSTMAN chrome app. My JSON looks like this.
{
"resultset": {
"violations": {
"hpd": [
{
"0": {
"ViolationID": "110971",
"BuildingID": "775548",
"RegistrationID": "500590",
"Boro": "STATEN ISLAND",
"HouseNumber": "275",
"LowHouseNumber": "275",
"HighHouseNumber": "275",
"StreetName": "RICHMOND AVENUE",
"StreetCode": "44750",
"Zip": "10302",
"Apartment": "",
"Story": "All Stories ",
"Block": "1036",
"Lot": "1",
"Class": "A",
"InspectionDate": "1997-04-11",
"OriginalCertifyByDate": "1997-08-15",
"OriginalCorrectByDate": "1997-08-08",
"NewCertifyByDate": "",
"NewCorrectByDate": "",
"CertifiedDate": "",
"OrderNumber": "772",
"NOVID": "3370",
"NOVDescription": "§ 27-2098 ADM CODE FILE WITH THIS DEPARTMENT A REGISTRATION STATEMENT FOR BUILDING. ",
"NOVIssuedDate": "1997-04-22",
"CurrentStatus": "VIOLATION CLOSED",
"CurrentStatusDate": "2015-03-10"
},
"count": "1"
}
]
}
},
"count": "1",
"total_page": 1,
"current_page": 1,
"limit": [
"0",
"1000"
],
"status": "success",
"error_code": "",
"message": ""
}
I am trying to test whether my response body has "ViolationID":"110971".
I tried the below code in postman:
var jsonData =JSON.parse(responseBody);
tests["Getting Violation Id"] = jsonData.resultset.violations.hpd[0].ViolationID === 110971;
Two issues I noticed in the provided data. The following suggestions might help you:
Add missing closing braces at the end.
Add missing 0 in the index like this: resultset.violations.hpd[0].0.ViolationID
If the hpd array always contains only 1 member, the test might be pretty straightforward:
pm.test('Body contains ViolationID', () => {
const jsonBody = pm.response.json();
const violationId = jsonBody.resultset.violations.hpd[0]["0"].ViolationID;
pm.expect(parseInt(violationId)).to.eql(110971);
})
However, if hpd array might contain more than one member, it gets a bit trickier. I would suggest mapping only ViolationID keys from nested objects:
pm.test('Body contains ViolationID', () => {
const jsonBody = pm.response.json();
const violationIds = jsonBody.resultset.violations.hpd.map(hpd => hpd["0"].ViolationID);
pm.expect(violationIds).to.contain('110971');
})
I'm new to rest-assured and I'm currently spiking it in order to implement it in our testing framework.
The problem I'm facing is to extract an object from a Json array from the REST response.
The example json I'm using:
{
"MRData": {
"xmlns": "http://ergast.com/mrd/1.4",
"series": "f1",
"url": "http://ergast.com/api/f1/2016/drivers.json",
"limit": "30",
"offset": "0",
"total": "24",
"DriverTable": {
"season": "2016",
"Drivers": [
{
"driverId": "alonso",
"permanentNumber": "14",
"code": "ALO",
"url": "http://en.wikipedia.org/wiki/Fernando_Alonso",
"givenName": "Fernando",
"familyName": "Alonso",
"dateOfBirth": "1981-07-29",
"nationality": "Spanish"
},
{
"driverId": "bottas",
"permanentNumber": "77",
"code": "BOT",
"url": "http://en.wikipedia.org/wiki/Valtteri_Bottas",
"givenName": "Valtteri",
"familyName": "Bottas",
"dateOfBirth": "1989-08-28",
"nationality": "Finnish"
}
]
}
}
}
Things i have tried so far:
This assertion is working
RestAssured.rootPath = "MRData.DriverTable.Drivers";
given()
.when()
.get("http://ergast.com/api/f1/2016/drivers.json")
.then()
.assertThat()
.body("find { find { d -> d.driverId == 'alonso' }.code }.code", equalTo("ALO"));
But I'm trying to actually get the Json of the particular array item
RestAssured.rootPath = "MRData.DriverTable.Drivers";
given()
.when()
.get("http://ergast.com/api/f1/2016/drivers.json")
.then()
.extract()
//.jsonPath().param("driverId", "alonso").get("find { d -> d.driverId == driverId }");
.path("find { d -> d.driverId == 'alonso' }");
Tried with both ways (one is commented out). But I get an error :
"The parameter "driverId" was used but not defined. Define parameters using the JsonPath.params(...)"
RestAssured.rootPath = "MRData.DriverTable.Drivers"; works only for body expectations. For extraction you have to use full path to paramter e.g. MRData.DriverTable.Drivers.find { it.#driverId == 'alonso' }
I have desktop application which reads Facebook Messages (unified_message in FQL terms), which left on my Facebook Page by other Users.
The problem is: when User writes message, which include link, Facebook automatically attaches some object to the message. And this attachment causes exception in RestFb Lib. Unfortunately, my Page access token will not help, because you have to be logged in as me in Facebook in order to use it. But scenario is very simple, try to leave message on a Page like “www.wheather.com - cool site”. I’ve tried it with RestFb 1.6.9 and 1.6.11 – the same result for both.
Sorry for formatting. I couldn't do it in other way :(
Here is stack for 1.6.11:
com.restfb.exception.FacebookJsonMappingException: Unable to convert Facebook response JSON to a list of java.lang.String instances. Offending JSON is {"38d79791ef0dac6f0b645a87f4d152d7":{"icon":"https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif","fb_object_type":"","tagged_ids":[],"description":"The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.","name":"National and Local Weather Forecast, Hurricane, Radar and Report","fb_object_id":"","caption":"www.weather.com","properties":[],"media":[],"href":"http://www.weather.com/"}}
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:171)
at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:653)
at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:290)
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:181)
at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:653)
at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:290)
at myprogram.MyDefaultFacebokClient.executeMultiquery(MyDefaultFacebokClient.java:62)
Caused by: com.restfb.json.JsonException: JsonObject["data"] not found.
at com.restfb.json.JsonObject.get(JsonObject.java:525)
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:155)
... 17 more
Here is stack for 1.6.9:
com.restfb.exception.FacebookJsonMappingException: Unable to convert Facebook response JSON to a list of java.lang.String instances. Offending JSON is {"38d79791ef0dac6f0b645a87f4d152d7":{"icon":"https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif","fb_object_type":"","tagged_ids":[],"description":"The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.","name":"National and Local Weather Forecast, Hurricane, Radar and Report","fb_object_id":"","caption":"www.weather.com","properties":[],"media":[],"href":"http://www.weather.com/"}}
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:167)
at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:602)
at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:279)
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:177)
at com.restfb.DefaultJsonMapper.toJavaType(DefaultJsonMapper.java:602)
at com.restfb.DefaultJsonMapper.toJavaObject(DefaultJsonMapper.java:279)
at myprogram.MyDefaultFacebokClient.executeMultiquery(MyDefaultFacebokClient.java:62)
. . .
Caused by: com.restfb.json.JsonException: JsonObject["data"] not found.
at com.restfb.json.JsonObject.get(JsonObject.java:525)
at com.restfb.DefaultJsonMapper.toJavaList(DefaultJsonMapper.java:151)
... 17 more
Here is FQL request:
{
"users":"SELECT uid,first_name,middle_name,last_name,name,pic_small,pic_big,profile_update_time,timezone,religion,birthday,birthday_date,sex,hometown_location,relationship_status,political,current_location,about_me,notes_count,wall_count,status,locale,profile_url,verified,profile_blurb,username,is_blocked,email,friend_count,languages FROM user WHERE uid IN (SELECT sender FROM #messages)"
,"msg":"SELECT message_id FROM unified_message WHERE thread_id='t_id.238275946308607' AND timestamp > '1360112817564' AND sender.user_id != '507447822604742' LIMIT 100"
,"messages":"SELECT message_id,thread_id,subject,body,unread,action_id,timestamp,tags,sender,recipients,object_sender,html_body,attachments,shares,share_map FROM unified_message WHERE message_id IN (SELECT message_id FROM #msg) AND timestamp > '1360112817564' AND timestamp <= '1360117314920' LIMIT 100"
}
Here is reply from Facebook Explorer on request above:
{
"data": [
{
"name": "msg",
"fql_result_set": [
{
"message_id": "m_mid.1360112949050:d17ca4ed7fc6236a75"
}
]
},
{
"name": "messages",
"fql_result_set": [
{
"message_id": "m_mid.1360112949050:d17ca4ed7fc6236a75",
"thread_id": "t_id.238275946308607",
"subject": null,
"body": "Have a look on http://www.weather.com 1",
"unread": true,
"action_id": "1360112949128000000",
"timestamp": "1360112949058",
"tags": [
"inbox",
"source:web"
],
"sender": {
"name": "Adam Client",
"email": "100004967623158#facebook.com",
"user_id": "100004967623158"
},
"recipients": [
{
"name": "MB Aerospace Corp.",
"email": "507447822604742#facebook.com",
"user_id": "507447822604742"
},
{
"name": "Adam Client",
"email": "100004967623158#facebook.com",
"user_id": "100004967623158"
}
],
"object_sender": null,
"html_body": "Have a look on http://www.weather.com 1",
"attachments": [
],
"shares": [
"38d79791ef0dac6f0b645a87f4d152d7"
],
"share_map": {
"38d79791ef0dac6f0b645a87f4d152d7": {
"media": [
],
"name": "National and Local Weather Forecast, Hurricane, Radar and Report",
"href": "http://www.weather.com/",
"caption": "www.weather.com",
"description": "The Weather Channel and weather.com provide a national and local weather forecast for cities, as well as weather radar, report and hurricane coverage.",
"properties": [
],
"fb_object_type": "",
"fb_object_id": "",
"icon": "https://fbstatic-a.akamaihd.net/rsrc.php/v2/yD/r/aS8ecmYRys0.gif",
"tagged_ids": [
]
}
}
}
]
},
{
"name": "users",
"fql_result_set": [
{
"uid": 100004967623158,
"first_name": "Adam",
"middle_name": "",
"last_name": "Client",
"name": "Adam Client",
"pic_small": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash4/371585_100004967623158_2019810380_t.jpg",
"pic_big": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash4/371585_100004967623158_2019810380_n.jpg",
"profile_update_time": 1360108999,
"timezone": null,
"religion": null,
"birthday": null,
"birthday_date": null,
"sex": "male",
"hometown_location": null,
"relationship_status": null,
"political": null,
"current_location": null,
"about_me": null,
"notes_count": null,
"wall_count": null,
"status": null,
"locale": "en_US",
"profile_url": "https://www.facebook.com/adam.client.5",
"verified": null,
"profile_blurb": null,
"username": "adam.client.5",
"is_blocked": false,
"email": null,
"friend_count": 1,
"languages": [
]
}
]
}
]
}
And the last one. I use redefined FacebookClient. The source was taken from here, stackoverflow.com. I don’t remember exactly why but it was something like DefaultFacebookClient could not correctly map results from Facebook (attachments to Messages).
public class MyDefaultFacebokClient extends DefaultFacebookClient {
#Override public <T> T executeMultiquery (Map<String, String> queries, Class<T> objectType, Parameter... parameters)
{
verifyParameterPresence("objectType", objectType);
for (Parameter parameter : parameters)
if (QUERY_PARAM_NAME.equals(parameter.name))
throw new IllegalArgumentException("You cannot specify the '" + QUERY_PARAM_NAME
+ "' URL parameter yourself - " + "RestFB will populate this for you with "
+ "the queries you passed to this method.");
try {
List<JsonObject> jsonObjects = jsonMapper.toJavaList(makeRequest("fql", false, false, null,
parametersWithAdditionalParameter(Parameter.with("q", queriesToJson(queries)), parameters)), JsonObject.class);
JsonObject normalizedJson = new JsonObject();
for (int i = 0; i < jsonObjects.size(); i++)
{
JsonObject jsonObject = jsonObjects.get(i);
// For empty result sets, Facebook will return an empty object instead of
// an empty list. Hack around that here.
JsonArray resultsArray =
jsonObject.get("fql_result_set") instanceof JsonArray ? jsonObject.getJsonArray("fql_result_set")
: new JsonArray();
normalizedJson.put(jsonObject.getString("name"), resultsArray);
}
return objectType.equals(JsonObject.class) ? (T) normalizedJson : jsonMapper.toJavaObject(normalizedJson.toString(), objectType);
} catch (JsonException e) {
throw new FacebookJsonMappingException("Unable to process fql.multiquery JSON response", e);
}
}
}
Any ideas will be very appreciated.
I'm the author of RestFB. Maybe pull the latest from Github, run "ant dist" to create the 1.6.12 JAR, and try calling the new FacebookClient.executeFqlMultiquery method instead of FacebookClient.executeMultiquery().
The new Graph API FQL endpoint is a little different that the old one and this new executeFqlMultiquery() method should hopefully fix the problem you're seeing. Let me know if not, or if you're having problems mapping the result type correctly.
Here's a quick example of how you might use the new method, copied from https://groups.google.com/forum/?fromgroups=#!topic/restfb/yjCxSQuiieE:
static void test() throws Exception {
FacebookClient facebookClient = new DefaultFacebookClient("xxx");
final String threadsFql =
"SELECT action_id, archived, can_reply, folder, former_participants, has_attachments, "
+ "is_subscribed, last_visible_add_action_id, name, num_messages, num_unread, object_participants, "
+ "participants, senders, single_recipient, snippet, snippet_sender, snippet_message_has_attachment, "
+ "subject, tags, thread_id, thread_participants, timestamp, unread "
+ "FROM unified_thread WHERE folder='inbox' AND has_attachments='1'";
final String messagesFql =
"SELECT message_id, thread_id, subject, body, unread, action_id, timestamp, tags, sender, recipients, "
+ "object_sender, html_body, attachments, attachment_map, shares, share_map "
+ "FROM unified_message WHERE thread_id IN (SELECT thread_id FROM #threads) LIMIT 2";
ComplexMappingResults results = facebookClient.executeFqlMultiquery(new HashMap<String, String>() {
{
put("threads", threadsFql);
put("messages", messagesFql);
}
}, ComplexMappingResults.class);
out.println(results);
}
public static class ComplexMappingResults {
#Facebook
private List<Thread> threads;
#Facebook
private List<Message> messages;
#Override
public String toString() {
return ReflectionUtils.toString(this);
}
public List<Thread> getThreads() {
return threads;
}
public List<Message> getMessages() {
return messages;
}
}