Alamofire POST Request - json

I was hoping someone could explain what the POST request (with parameters) accomplishes. When I run the following command, provided by Alamofire's documentation, this is what is produced:
Code
let url = "https://httpbin.org/post"
let parameters: Parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
if((response.result.value) != nil) {
let jsonVar: JSON = JSON(response.result.value!)
print(jsonVar)
}
}
Result
{
"files" : {
},
"origin" : "192.104.181.247",
"data" : "{\"baz\":[\"a\",1],\"qux\" {\"y\":2,\"x\":1,\"z\":3},\"foo\":\"bar\"}",
"headers" : {
"Accept" : "*\/*",
"Accept-Encoding" : "gzip;q=1.0, compress;q=0.5",
"Content-Type" : "application\/json",
"Host" : "httpbin.org",
"Content-Length" : "53",
"User-Agent" : "HTTPRequest\/1.0 (com.dexstrum.HTTPRequest; build:1; iOS 10.2.0) Alamofire\/4.3.0",
"Accept-Language" : "en;q=1.0"
},
"json" : {
"baz" : [
"a",
1
],
"foo" : "bar",
"qux" : {
"x" : 1,
"y" : 2,
"z" : 3
}
},
"form" : {
},
"args" : {
},
"url" : "https:\/\/httpbin.org\/post"
}
What exactly is occurring with the parameters and the POST request?

The url you are hitting it allows a post request. You can get json response by get or post method. Usually you fetch data by get method and send data by post method. When sending data with post request it needs some parameter to satisfy its requirement , usually its predefined.
SO you are sending a post request here with alamofire and along with some parameter which satisfy its requirements. Here you are encoding the parameter as JSONEncoding.default which means it sends the parameter data encoded as json finally you get the response as json coz you declared .responseJSON . Hope that helps.

Related

How to retrieve all key-value pairs avoiding key duplication from JSON in Groovy script

I am totally new to groovy script and would like some help to solve this out. I have a JSON response I want to manipulate and get desired parameters back by avoiding duplication. The Json response does not have indexes like 0,1,2.. that I can iterate through.
Here is the response that I want to work with:
{
"AuthenticateV2" : {
"displayName" : "Verification of authentication",
"description" : "notification ",
"smsTemplate" : "authentication.v2.0_sms",
"emailHeaderTemplate" : "v2.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE"
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordRecovery" : {
"displayName" : "Verification of password recovery",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "recovery.v1.0_body_html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordReset" : {
"displayName" : "password reset",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
}
The expected output that I want to have:
{
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL"
}
I need to retrieve all fields under parameters tag and also want to avoid duplication
You should first get familiar with parsing and producing JSON in Groovy.
Then, assuming the provided response is a valid JSON (it's not - there are 2 closing curlies (}) missing at the end) to get all the parameters keys merged into one JSON we have to convert the JSON string into a Map object first using JsonSlurper:
def validJsonResponse = '<your valid JSON string>'
Map parsedResponse = new JsonSlurper().parseText(validJsonResponse) as Map
Now, when we have a parsedResponse map we can iterate over all the root items in the response and transform them into the desired form (which is all the unique parameters keys) using Map::collectEntries method:
Map uniqueParameters = parsedResponse.collectEntries { it.value['parameters'] }
Finally, we can convert the uniqueParameters result back into a pretty printed JSON string using JsonOuput:
println JsonOutput.prettyPrint(JsonOutput.toJson(uniqueParameters))
After applying all the above we'll get the output
{
"displayName": "USER_DISPLAY_NAME",
"actionTokenURL": "VERIFICATION_LINK",
"customToken": "VERIFICATION_CODE",
"adminInitiated": false,
"authnId": "AUTHENTICATION_IDENTIFIER",
"authnType": "EMAIL",
"user": {
"displayName": "USER_DISPLAY_NAME"
}
}
If you want to get rid of user entry from the final output just remove it from the resulting uniqueParameters map (uniqueParameters.remove('user')) before converting it back to JSON string.

Post data containing array of structs in swift

Here is the JSON I need to post:
{
"results": [
{
"case_id": 1,
"status_id": 5,
"comment": "This test failed"
},
{
"case_id": 2,
"status_id": 1,
"comment": "This test passed",
},
..
{
"case_id": 1,
"assignedto_id": 5,
"comment": "Assigned this test to Joe"
}
..
]
}
What I've tried doing is this :
let parameters = [
"results" : data
] as [String : Any]
let postData = try JSONSerialization.data(withJSONObject: parameters, options: [])
Here, data is an array of structs of the type (data:[param]) :
struct param {
var status_id: Int
var case_id: String
var comment: String
}
The code fails at JSONSerialization. It enters the catch() block. I tried giving the parameters like this and it worked,
let parameters = [ "results" : [
[
"case_id": "20275",
"status_id": 5,
"comment": "This test failed"
],
[
"case_id": "20276",
"status_id": 1,
"comment": "This test passed",
],
]] as [String : Any]
How can I reproduce this structure? Because I can't hard code the values of status id's and case id's. I store the status id's and case id's in arrays.I thought creating an array of structs and substituting the id values will be enough, unfortunately it's not working. How do I post the data then?
The 'param' should be a dictionary do not make it with struct.
The request body data type is: [String:[[String,Any]]]

My JSON parsing fails

Im using SwiftyJSON, Alamofire_SwiftyJSON and Alamofire libraries. I'm trying to parse my response but it returns nothing("definitions" fails to print).
JSON isn't empty it has got the response.
So, my code looks like the following (nothing fails, it all compiles)
Alamofire.request(request).responseSwiftyJSON { dataResponse in
if let JSON = dataResponse.result.value {
print(JSON)
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string {
print(definitions)
print("Hello")
}}
}
My response model looks like (this is not the whole response, that's just what I want to reach :
{
"results" : [
{
"language" : "en",
"id" : "ace",
"type" : "headword",
"lexicalEntries" : [
{
"language" : "en",
"entries" : [
{
"etymologies" : [
"Middle English (denoting the ‘one’ on dice): via Old French from Latin as ‘unity, a unit’"
],
"grammaticalFeatures" : [
{
"type" : "Number",
"text" : "Singular"
}
],
"homographNumber" : "000",
"senses" : [
{
"definitions" : [
"a playing card with a single spot on it, ranked as the highest card in its suit in most card games"
I think that my problem is in, should I add any parentheses or any symbols?
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string
You are not indexing the corresponding arrays in your JSON response, to access the definitions array you can simply use
JSON['results'][0]['lexicalEntries'][0]['entries'][0]['senses'][0]['definitions']

(Swift) twilio post request to set attributes using alamofire

I am attempting to use Twilio's REST Api and Alamofire to set certain Attributes to a Channel when creating it (https://www.twilio.com/docs/api/ip-messaging/rest/channels#action-create)
let parameters : [String : AnyObject] = [
"FriendlyName": "foo",
"UniqueName": "bar",
"Attributes": [
"foo": "bar",
"bar": "foo"
],
"Type": "private"
]
Alamofire.request(.POST, "https://ip-messaging.twilio.com/v1/Services/\(instanceSID)/Channels", parameters: parameters)
.authenticate(user: user, password: password)
.responseJSON { response in
let response = String(response.result.value)
print(response)
}
Using that code, the response I received back was that a Channel was created with FriendlyName foo and UniqueName bar, but that Channel had no Attributes set.
Looking at the Alamofire github (https://github.com/Alamofire/Alamofire) I see that there's a way to send a POST Request with JSON-encoded Parameters. So I tried this:
let parameters : [String : AnyObject] = [
"FriendlyName": "foo",
"UniqueName": "bar15",
"Attributes": [
"foo": "bar",
"bar": "foo"
],
"Type": "private"
]
Alamofire.request(.POST, "https://ip-messaging.twilio.com/v1/Services/\(instanceSID)/Channels", parameters: parameters, encoding: .JSON)
.authenticate(user: user, password: password)
.responseJSON { response in
let response = String(response.result.value)
print(response)
}
When adding "encoding: .JSON" to the request the response shows that not only were the Attributes not set but also the FriendlyName and UniqueName were nil, unlike before when they were correctly set using the URL-Encoded Parameters.
Am I setting the Attributes wrong in 'parameters'? Twilio's documentation says that Attributes is "An optional metadata field you can use to store any data you wish. No processing or validation is done on this field."
Help would be appreciated :)
I have figured out an answer to my question. Turns out I had formatted the Attributes field incorrectly.
Here is the code that worked for me:
let parameters : [String : AnyObject] = [
"FriendlyName": "foo",
"UniqueName": "bar",
"Attributes": "{\"key\":\"value\",\"foo\":\"bar\"}",
"Type": "private"
]
Alamofire.request(.POST, "https://ip-messaging.twilio.com/v1/Services/\(instanceSID)/Channels/", parameters: parameters)
.authenticate(user: user, password: password)
.responseJSON { response in
let response = String(response.result.value)
print(response)
debugPrint(response)
}
Hope this helps others :)

Matching data in JsonPath with wiremock

I'm trying to create mocks for my login procedure. I use POST method with a couple of fields and login object (with login, password, etc.)
For that I'm using JsonPath. Code below:
{
"request": {
"method": "POST",
"url": "/login",
"bodyPatterns" : [
{"matchesJsonPath" : "$.method"},
{"matchesJsonPath" : "$.params[?(#.clientVersion == "1")]"},
{"matchesJsonPath" : "$.params.login"},
{"matchesJsonPath" : "$.params.password"}
]
},
"response": {
"status": 200,
"bodyFileName": "login.json"
}
}
I'm checking the clientVersion because it's similar to the examples.
My problem is, that with te given POST JSON:
{
"method": "login",
"params": {
"clientVersion": "1",
"login": "test#test.com",
"password": "681819535da188b6ef2"
}
}
I receive 404.
However, when I change
{"matchesJsonPath" : "$.params[?(#.clientVersion == "1")]"},
to normal
{"matchesJsonPath" : "$.params.clientVersion"},
everything works just fine.
So - how to check inside wiremock, using matchesJsonPath if given field equals some value?
How to apply it to the root field like method in my case?
And while we're at it - I had similar problems with checking if the value is not null. I tried to apply regular expressions and such - no luck.
It's working in my case :
wiremock:
"request": {
"urlPathPattern": "/api/authins-portail-rs/authins/inscription/infosperso",
"bodyPatterns" : [
{"matchesJsonPath" : "$[?(#.nir == '123456789')]"},
{"matchesJsonPath" : "$[?(#.nomPatronyme == 'aubert')]"},
{"matchesJsonPath" : "$[?(#.prenoms == 'christian')]"},
{"matchesJsonPath" : "$[?(#.dateNaissance == '01/09/1952')]"}
],
"method": "POST"
}
Json:
{
"nir": "123456789",
"nomPatronyme": "aubert",
"prenoms": "christian",
"dateNaissance": "01/09/1952"
}
Following worked for me.
"matchesJsonPath" : "$.rootItem.itemA[0].item..[?(#.fieldName=='file')]"
Json :
{
"rootItem" : {
"itemA" : [
{
"item" : {
"fieldName" : "file",
"name" : "test"
}
}
]
}
}
Wiremock
{
"request" : {
"urlPattern" : "/testjsonpath",
"method" : "POST",
"bodyPatterns" : [ {
"matchesJsonPath" : "$.rootItem.itemA[0].item..[?(#.fieldName=='file')]"
} ]
},
"response" : {
"status" : 200,
"body" : "{\"result\": \"success\"}",
"headers" : {
"Content-Type" : "application/json"
}
}
}
Update Wiremock. It should work with newer versions >= 2.0.0-beta. Its JsonPath dependency was very outdated (GitHub #261).
Using the double dots operator is semantically not the same, as the filter will also match for elements with the same name deeper down the tree.
try with double dots operator (recursive)
$..params[?(#.clientVersion == "1")]