Iteract through __NSSingleObjectArrayI in Objective-C - objective-c

I'm getting the below response and how do I iterate or get the values?
<__NSSingleObjectArrayI 0x600002edeea0>(
{
link = "<null>";
ValueG = "%";
ValueT = 1;
ValueV = "5.00";
ValueS = "%";
ValueGTX = 1;
ValueGT = "5.00";
ValueZH = 1;
time = 30;
UG = “test”;
ValueSFS = "%";
ValueFT = 1;
ValueSFV = "5.00";
SID = “000”;
SN = Test;
ST = "";
ValueTV = "10.00";
"__type" = “WSDInfo”;
}
)
This is how I tried to get the value, but it is throwing the following error Expected method to read array element not found on object of type 'NSDictionary *'
self.valuesInfo = [MTLJSONAdapter modelOfClass:self.valueType.storeInfoClass
fromJSONDictionary:JSON
error:NULL];
NSDictionary *storeInfoDict = JSON;
if (storeInfoDict.count != 0) {
for (int i=0; i <= storeInfoDict.count; i++){
NSString *ValueG = storeInfoDict[i][#"ValueG"];
}
}
Below is the response from postman. In the code, "d" is removed by the JSONResponseSerializer
{
"d": [
{
"__type": "WSDInfo",
"SID": “000”,
“SN”: “Test”,
“ST”: "",
"UG": “Test”,
"time": "30",
"ValueTV": "10.00",
"ValueG": "%",
"ValueV": "5.00",
"ValueT": "1",
"ValueSFS": "%",
"ValueGT": "5.00",
"ValueGTX": "1",
"ValueS": "%",
"ValueSFV": "5.00",
"ValueZH": "1",
"ValueFT": true,
"link": null
}
]
}

Related

UKG Dimensions Number of employees in request (624) exceeds allowed limit (500)

This error occurs when you are requesting aggregated data using the URL:
POST - {{DIMENSIONSHOST}}/v1/commons/data/multi_read
The Postman body that I used was:
{
"select": [
{"key": "EMP_COMMON_FULL_NAME"}
],
"from": {
"view": "EMP",
"employeeSet": {
"hyperfind": {
"id": -9
},
"dateRange": {
"startDate": "2022-01-01",
"endDate": "2022-04-30"
}
}
},
"index": 0,
"count": 500
}
Notice that I requested "count": 500. Even though I requested only 500 records, I got the error message that there were more than 500 records.
This identifies a bug in UKG Dimensions. I have developed a work around:
Retrieve the hyperfind by itself using /v1/commons/hyperfind/execute
Use a Postman Test (a post-response program) to split the IDs into batches of 500.
Save the batches to an environment variable
Use the environment variable for the aggregated data request.
You can retrieve the hyperfind by itself using:
POST - {{DIMENSIONSHOST}}/v1/commons/hyperfind/execute
The body of the request is:
{
"dateRange": {
"startDate": "2022-05-01",
"endDate": "2022-06-30"
},
"hyperfind": {
"id": -9
},
"includeTerminatedInRangeForLocations": true
}
The test script is:
var jsonData = JSON.parse(responseBody); //the data from the response body
var allIDs = []; //an array of all the IDs, no record count limit
var max500IDs = []; //arrays of maximum number of IDs
//
//retrieve all the IDs and put them into an array called allIDs
//
for(var i = 0; i < jsonData.result.refs.length; i++) {
allIDs.push(jsonData.result.refs[i].id );
}
var batchCount = 1; //number of batches - default 1
var IDsInBatch = 500; //maximum number of records in batch
//
//calculate the number of batches that you will need
//
if(allIDs.length > IDsInBatch) {
batchCount = Math.ceil((allIDs.length - 1) / IDsInBatch);
}
//
//loop through the number of batches
//
var eeCountInOtherBatches = 0;
for(var k = 0; k < batchCount; k++) {
//
//loop through all the IDs and transfer them to a max 500 batch
//
var batch = []
for(var j = 0; j < IDsInBatch; j++) {
personID = allIDs[eeCountInOtherBatches + j];
if(personID) {
batch.push(personID);
}
}
max500IDs[k] = batch;
eeCountInOtherBatches = eeCountInOtherBatches + IDsInBatch;
}
//
//transfer the batches to environment variable(s)
//
for(var x = 0; x < max500IDs.length; x++) {
postman.setEnvironmentVariable("max500IDs_" + x, max500IDs[x]);
}
The environment variables will be:
max500IDs_0
max500IDs_1
etc.
The employee request would be something like:
POST - {{DIMENSIONSHOST}}/v1/commons/data/multi_read
The body would be:
{
"select": [
{"key": "EMP_COMMON_FULL_NAME"}
],
"from": {
"view": "EMP",
"employeeSet": {
"employees": {
"ids": [{{max500IDs_0}}]
},
"dateRange": {
"startDate": "2022-01-01",
"endDate": "2022-04-30"
}
}
},
"index": 0,
"count": 500
}

Karate - How change key name in JSON

I have the following JSON. I want to change the keyName 'freeDelivery' to 'isFreeDelivery' but I can't figure out how to do it.
{
"result": [
{
"deliverySlots": [
{
"id": "2DNN",
"date": "2022-04-05",
"freeDelivery": false,
"label": "All day delivery 08:30am to 5pm",
"price": "£5.00",
"fullSlotId": "2DNN"
},
{
"id": "2DPM",
"date": "2022-04-05",
"freeDelivery": false,
"label": "Afternoon 12pm to 5pm",
"price": "£10.00",
"fullSlotId": "2DPM"
}
]
},
{
"deliverySlots": [
{
"id": "2DNN",
"date": "2022-04-06",
"freeDelivery": false,
"label": "All day delivery 08:30am to 5pm",
"price": "£5.00",
"fullSlotId": "2DNN"
},
{
"id": "2DPM",
"date": "2022-04-06",
"freeDelivery": false,
"label": "Afternoon 12pm to 5pm",
"price": "£10.00",
"fullSlotId": "2DPM"
}
]
}
]
}
I've looked at the following pages but still can't figure out how to do it. Do I have to do a transorm or is there an easier way?
https://github.com/karatelabs/karate/blob/master/karate-junit4/src/test/java/com/intuit/karate/junit4/demos/js-arrays.feature
https://github.com/karatelabs/karate#json-transforms
Here you go:
* def payload = { before: 'foo' }
* remove payload.before
* payload.after = 'bar'
* match payload == { after: 'bar' }
Instead of remove this will also work (using pure JS):
* eval delete payload.before
EDIT: after seeing the comments, I would treat this as a JSON transform.
* def payload = { before: 'foo' }
* def fun = function(x){ var res = {}; res.after = x.before; return res }
* def result = fun(payload)
* match result == { after: 'foo' }
I'm sure now you'll want to "retain" all the existing data. Fine, here you go:
* def payload = { before: 'foo' }
* def fun = function(x){ var res = x; res.after = x.before; delete res.before; return res }
* def result = fun(payload)
* match result == { after: 'foo' }
And you already know that you can run a transform on all array elements like this:
* def result = karate.map(someArray, fun)
Please note that you can create 2 or 3 transforms - and "nest" them.

Need to retrieve the json key value as null if key not present at the node

{
"a": {
"b": 1,
"c": 0
},
"values": [
{
"d": "WERTY",
"e": "details",
"f": [
{
"addressId": "vvvv",
"address": "ffff"
}
]
},
{
"d": "ZXCVB",
"e": "details"
},
{
"d": "ASDFG",
"e": "details",
"f": [
{
"addressId": "vvvv",
"address": "xxxx"
}
]
}
]
}
After getting the response from restassured, I am trying to fetch the values of a particular key with JsonPath.
I am using:
responseBody.jsonPath().getList("values.f.address)
This is returning me a list - ["ffff","xxxx"]
I want to get - ["ffff",null,"xxxx"]
Is it possible to achieve this with Karate?
JsonPath = values[0].f[0].address
If you are using validatableResonse then you can use:
String res_str = Response.extract().jsonPath().getString("values[0].f[0].address");
The response should be of ValidatableResponse type.
It won't return you null for that absent item, because field address is actually not present in the response body.
You can do it checking whether the f key is available in each object of values array;
If it is available -> add the value of address in each object in f array, to a String list
If it is not available -> add null to the same String list.
I create a org.json.JSONObject from io.restassured.response.Response.
Response response = given()
.when()
.get(url)
.then()
.extract()
.response();
List<String> addressList = new ArrayList<>();
JSONObject responseObject = new org.json.JSONObject(response.body().asString());
JSONArray jsonArray = responseObject.getJSONArray("values");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
if (jsonObject.keySet().contains("f")) {
JSONArray fObjectArray = jsonObject.getJSONArray("f");
for (int j = 0; j < fObjectArray.length(); j++) {
addressList.add(fObjectArray.getJSONObject(j).get("address").toString());
}
} else {
addressList.add(null);
}
}
System.out.println(addressList.toString());
This will print the following result;
[ffff, null, xxxx]

Getting the maximum value from an array in a JSON response in Karate

I have the following Json as a response from a API call
{
"location": {
"name": "London",
"region": "City of London, Greater London",
"country": "United Kingdom",
"lat": 51.52,
"lon": -0.11,
"tz_id": "Europe/London",
"localtime_epoch": 1583594426,
"localtime": "2020-03-07 15:20"
},
"forecast": {
"forecastday": [
{
"date": "2020-03-03",
"day": {
"maxtemp_c": 9,
"mintemp_c": 4
}
},
{
"date": "2020-03-04",
"day": {
"maxtemp_c": 8,
"mintemp_c": 4.1
}
},
{
"date": "2020-03-05",
"day": {
"maxtemp_c": 7,
"mintemp_c": 5.6
}
}
]
}
}
I want to find out which date had the highest temperature amongst the 3 days.
The way I am currently doing feels inefficient as I am checking for the temperature element within my js function and it is as follows
* def hottest =
"""
function(array) {
var greatest;
var indexOfGreatest;
for (var i = 0; i < array.length; i++) {
if (!greatest || array[i].day.maxtemp_c > greatest) {
greatest = array[i].day.maxtemp_c;
indexOfGreatest = i;
}
}
return indexOfGreatest;
}
"""
* def index = call hottest response.forecast.forecastday
* def hottestdate = response.forecast.forecastday[index].date
* print hottestdate
With this I am getting the correct result but can someone kindly suggest a better way of doing this?
Best practice in Karate is to NOT use JS for loops at all. It results in cleaner, more readable code:
* def fun = function(x){ return { max: x.day.maxtemp_c, date: x.date } }
* def list = karate.map(response.forecast.forecastday, fun)
* def max = 0
* def index = 0
* def finder =
"""
function(x, i) {
var max = karate.get('max');
if (x.max > max) {
karate.set('max', x.max);
karate.set('index', i);
}
}
"""
* karate.forEach(list, finder)
* print 'found at index', index
* print 'item:', list[index]
Note how easy it is to re-shape a given JSON, the result of list here would be:
[
{
"max": 9,
"date": "2020-03-03"
},
{
"max": 8,
"date": "2020-03-04"
},
{
"max": 7,
"date": "2020-03-05"
}
]

Form dictionary as a parameter in PUT API request - AFNetworking

Hi I have to update my records to the server using REST API.
I'm using AFNetworking Library and forming the PUT request parameter format as below
{
"type":"goal",
"field_weight_goal": {
"und": [
{
"value": "60"
}
]
},
"field_weight_actual": {
"und": [
{
"value": "90"
}
]
},
"field_weight_date": {
"und": [
{
"value": "05-10-2017",
"format": null,
"safe_value": "05-10-2017"
}
]
}
}
Below is my code.
NSDictionary *params = #{#"type": #"goal",
#"field_weight_goal" : #{#"und": #[ #{#"value": self.goalWeightTextField.text } ] },
#"field_weight_actual" : #{#"und": #[ #{#"value": self.currentWeightTextField.text } ] },
#"field_weight_date" : #{#"und": #[ #{#"value": currentDate, #"format" : [NSNull null] , #"safe_value" : currentDate } ] }
};
The value is not updating in the server and I'm getting error ... Request failed: unacceptable (406). Please help me to correct my dictionary format.
while debugging in xcode my parameter format as below
{
"field_weight_actual" = {
und = (
{
value = "100.0";
}
);
};
"field_weight_date" = {
und = (
{
format = "<null>";
"safe_value" = "04-18-2017";
value = "04-18-2017";
}
);
};
"field_weight_goal" = {
und = (
{
value = "90.0";
}
);
};
type = goal;
}