how to send JSON in post api using Alomofire SWIFT - iphone

I need to send JSON format in post api using alamofire in swift. Way data need to send is
{
"data": [{
"id": "1015683997",
"name": "Pawel"
}, {
"id": "108350039247",
"name": "Randeep"
}, {
"id": "115607797616",
"name": "Mohit"
}]
}
And way i am able to generate as of now is:
["data": {
data = (
{
id = 101583997;
name = "Pawel";
},
{
id = 108359247;
name = "Randeep";
},
{
id = 11567616;
name = "Mohit ";
}
);
}
]
Using the below mentioned way to generate json format.
for i in 0..<self.arrFriendsList.count
{
let dictFrndList:[String: AnyObject] = [
"id" : arrFriendsList[i].valueForKey("id")!,"name" : arrFriendsList[i].valueForKey("name")!
]
arrFrndList.addObject(dictFrndList)
}
Then,
let dictFBFrndList: [String: AnyObject] = [
"data":arrFrndList
]
Then,
let params: [String: AnyObject] = [
"access_token" : accessToken,
"data":dictFBFriends
]
So, please guide me. i have already spend more than a day on it. thanks in advance.

I second what Larme said, you should post "arrFrndList" at the params with key "data" but not dictFBFrndList.

Managed this way
let jsonData = try! NSJSONSerialization.dataWithJSONObject(arrFriendsList, options: NSJSONWritingOptions.PrettyPrinted)
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
print(jsonString)
let params: [String: AnyObject] = [
"access_token" : accessToken,
"data":jsonString
]

let options = NSJSONWritingOptions()
let data = try? NSJSONSerialization.dataWithJSONObject(parameters, options: options)
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string:"http:/myurl.com")
if let str = NSString(data: data!, encoding: NSUTF8StringEncoding) as? String {
print(str)
}
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
mutableURLRequest.setValue("your_access_token", forHTTPHeaderField: "Authorization")
mutableURLRequest.HTTPBody = data
mutableURLRequest.HTTPMethod = "POST"
Alamofire.request(mutableURLRequest).responseJSON(){
json in
if let value = json.result.value {
let _json = JSON(value)
if (!_json.isEmpty){
print(_json)
}
}
}
you can check how to seen your JSON array this code. Look at 5th cell code. This code will write your json array for you in output screen and you can coppy from there and paste in here then you will see how to send data.
Maybe this way can help you .

Related

How to handle dynamic keys with single element as value in Swift

I'm having a problem figuring out how to handle dynamic keys with a single value one level deep. I've seen a few examples but they appear to handle other cases.
Here's an example.
[
{ "asdofjiodi": "asdofidj.com" },
{ "sadjlkj": "iejjol.com" },
{ "ijijwjljlijl": "adsijf.com" },
{ "jgncmkz": "mlkjaoijf.com" }
]
Any ideas on how I accomplish this with Codable or CodingKey? This is what I'd like for the end result.
["asdofidj.com", "iejjol.com", "adsijf.com", "mlkjaoijf.com"]
let url = Bundle.main.url(forResource: "file", withExtension: "json")!
let data = try! Data(contentsOf: url)
let decoder = JSONDecoder()
// NOTE: The below line doesn't work because I'm not sure how to do the encoding/decoding
try? decoder.decode([[String: String]].self, from: data)
First of all, is not a valid JSON. A "Valid JSON" can be a JSON Array (multiple json objects) or a single JSON object (starts and ends with { and })
After cleaning this...
You are trying to make a dictionary (json object) from a data. You don't need JSONDecoder to accomplish this. Try using JSONSerialization with jsonObject static function...
let data = Data("{\"asdofjiodi\": \"asdofidj.com\",\"sadjlkj\": \"iejjol.com\",\"ijijwjljlijl\": \"adsijf.com\",\"jgncmkz\": \"mlkjaoijf.com\"}".utf8)
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
let values = json?.map({ $1 })
print(values)
I Hope I helped!
JSONSerialization Apple documentation
Here is a minimal working example, given the JSON in your question:
let json = """
[
{ "asdofjiodi": "asdofidj.com" },
{ "sadjlkj": "iejjol.com" },
{ "ijijwjljlijl": "adsijf.com" },
{ "jgncmkz": "mlkjaoijf.com" }
]
"""
let data = Data(json.utf8)
let decoder = JSONDecoder()
do {
let decodedJson = try decoder.decode([[String: String]].self, from: data)
let values = decodedJson.compactMap(\.values.first)
print(values)
} catch {
print("Error: \(error.localizedDescription)")
}
If this doesn't appear to work for you, it may be related to how you load in the JSON.

Passing the contents of a text file as JSON to httpBody

FIGURED IT OUT, See below:
I'm trying to create a program that can pass the contents of a text file to a http POST request in swift. I am storing filters for API queries that I am running in the text files, and would like to pass them as JSON objects(? I think, anyway) to request.httpBody in the request. I'm having problems converting the txt files to something that the httpBody can accept as data (json object?).
Here an example txt file. Filters in the same array are combined using OR logic. Arrays of filters are combined using AND logic, so I have to account for both cases.:
zero_RC.txt
{
"query": "Zero Response Code",
"filters": [
{
"filters": [
{
"field": "inventoryState",
"value": "CONFIRMED",
"type": "IN"
},
{
"field": "responseCode",
"value": "0",
"type": "EQ"
},
{
"field": "exception",
"value": "DNS lookup failed",
"type": "EQ"
}]
}]
}
This is the block that I'm trying to get to work. I believe that I need a JSON object, and can pass that to httpBody in the request below. But, still a beginner at this stuff.
// get JSON, somehow
let file = Bundle.main.path(forResource: "zero_RC", ofType: "txt")
let jsonData = file!.data(using: .utf8)
let JSON = try! JSONSerialization.data(withJSONObject: jsonData as Any, options: [])
if JSONSerialization.isValidJSONObject(JSON) {
print("Oh Yeah")
} else {
print("Nah bud, that ain't working")
}
// make the request
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("Basic \(loginData!)", forHTTPHeaderField: "Authorization")
request.httpBody = JSON
So am I taking a string and converting to data, then into a JSON object? I'm thoroughly confused as to how best to do this. I've searched and searched and all I'm finding is parsing articles, which don't exactly help.
Thanks ahead of time.
ANSWERED:
The problem was in the request.setValue. I needed to use Content-Type instead of Accept.
// get JSON
let path = Bundle.main.path(forResource: "zero_RC", ofType: "txt")
let data = try! Data(contentsOf: URL(fileURLWithPath: path!), options: .mappedIfSafe)
// make the request
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("Basic \(loginData!)", forHTTPHeaderField: "Authorization")
request.httpBody = data
Here's the solution firstly we will decode your json file into a data model, then will encode that data model object to the httpBody.
let path = Bundle.main.path(forResource: "zero_RC", ofType: "txt")
let data = try! Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
let jsonDecoder = JSONDecoder()
let json = try! jsonDecoder.decode(JsonObjModel.self, from: data)
// now encoding that jsonData to the http body
let encoder = JSONEncoder()
urlRequest.httpBody = try! encoder.encode(json)
The 'JsonObjModel' will be the following
// MARK: - JSONObjModel
struct JSONObjModel: Codable {
let query: String
let filters: [JSONObjModelFilter]
}
// MARK: - JSONObjModelFilter
struct JSONObjModelFilter: Codable {
let filters: [FilterFilter]
}
// MARK: - FilterFilter
struct FilterFilter: Codable {
let field, value, type: String
}

Alamofire: Send JSON with Array of Dictionaries

I have a data structure that looks like this in JSON:
[{
"value": "1",
"optionId": "be69fa23-6eca-4e1b-8c78-c01daaa43c88"
}, {
"value": "0",
"optionId": "f75da6a9-a34c-4ff6-8070-0d27792073df"
}]
Basically it is an array of dictionaries. I would prefer to use the default Alamofire methods and would not like to build the request manually. Is there a way to give Alamofire my parameters and Alamofire does the rest?
If I create everything by hand I get an error from the server that the send data would not be correct.
var parameters = [[String:AnyObject]]()
for votingOption in votingOptions{
let type = votingOption.votingHeaders.first?.type
let parameter = ["optionId":votingOption.optionID,
"value": votingOption.votingBoolValue
]
parameters.append(parameter)
}
let jsonData = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
let json = try! NSJSONSerialization.JSONObjectWithData(jsonData, options: .AllowFragments)
if let url = NSURL(string:"myprivateurl"){
let request = NSMutableURLRequest(URL: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = Method.POST.rawValue
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
AlamofireManager.Configured.request(request)
.responseJSON { response in
//Handle result
}
}
I have the same issue and resolved this way:
I created a new struct implementing the Alamofire's ParameterEncoding protocol:
struct JSONArrayEncoding: ParameterEncoding {
private let array: [Parameters]
init(array: [Parameters]) {
self.array = array
}
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
let data = try JSONSerialization.data(withJSONObject: array, options: [])
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
urlRequest.httpBody = data
return urlRequest
}
}
Then, I can do this:
let parameters : [Parameters] = bodies.map( { $0.bodyDictionary() })
Alamofire.request(url, method: .post, encoding: JSONArrayEncoding(array: parameters), headers: headers).responseArray { ... }
It worked for me. Hope can help someone else.
You can do something like this:
Alamofire.request(.POST, urlPath, parameters: params).responseJSON{ request, response, data in
//YOUR_CODE
}
Where parameters is [String:AnyObject] and yes Alamofire takes care of the rest.
Since it looks like you are using a manager you can do this
YOUR_ALAMOFIRE_MANAGER.request(.POST, url, parameters: params).responseJSON{ request, response, JSON in
//enter code here
}
Here is the source code:
public func request(
method: Method,
_ URLString: URLStringConvertible,
parameters: [String: AnyObject]? = nil,
encoding: ParameterEncoding = .URL,
headers: [String: String]? = nil)
-> Request
{
let mutableURLRequest = URLRequest(method, URLString, headers: headers)
let encodedURLRequest = encoding.encode(mutableURLRequest, parameters: parameters).0
return request(encodedURLRequest)
}
EDIT:
Since your data is currently [[String:AnyObject]] you will need to modify it so it is in the form [String:AnyObject]. One way you could do this i by doing this ["data":[[String:AnyObject]]]. You will probably have to change your api end point though.
You can provide parameter encoding for JSON POST request and it will send the data as JSON in request body.
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters, encoding: .JSON)
This is described in the ReadMe file of Alamofire github - https://github.com/Alamofire/Alamofire#post-request-with-json-encoded-parameters
let parameters = [
"foo": [1,2,3],
"bar": [
"baz": "qux"
]
]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters, encoding: .JSON)
// HTTP body: {"foo": [1, 2, 3], "bar": {"baz": "qux"}}

Working with Neo4j Rest API in Swift

i am quite new to iOS and Swift and now i want to use Neo4j, a Graph Database for persistent saving of my data.
I know there's a Lib named Theo for connecting to the Graph Database, but i want to use the REST API. Now i am not sure how to handle the HTTP-Request in order to get data from Database to my iOS-App written in Swift?
Anyone has some helpful clues for my?
Thanks hannes
The Theo library that you mention is a wrapper around the Neo4j REST API. The benefit of using such a library is that it takes care of things like JSON serialization, error handling, adding the correct headers to HTTP requests, etc.
You can use Cypher with the transactional Cypher REST API endpoint using Swift like this (Note: this uses the Alamofire library for handling the HTTP request.):
import Alamofire
let cypherStatement = "CREATE (:Person {name: 'Bob'})-[:LIKES]->(pizza:Food {type: 'Pizza'})<-[:LIKES]-(:Person {name: 'William'}) WITH pizza MATCH (p:Person)-[:LIKES]->(pizz) RETURN p.name AS name"
let endpoint = "http://localhost:7474/db/data/transaction/commit"
let requestBody = [
"statements": [
[
"statement": cypherStatement
]
]
]
Alamofire.request(.POST, endpoint, parameters: requestBody, encoding: .JSON)
.responseJSON { response in
debugPrint(response)
}
Which logs:
[Request]: <NSMutableURLRequest: 0x7fafcb637320> { URL: http://localhost:7474/db/data/transaction/commit }
[Response]: <NSHTTPURLResponse: 0x7fafcb81d480> { URL: http://localhost:7474/db/data/transaction/commit } { status code: 200, headers {
"Access-Control-Allow-Origin" = "*";
"Content-Length" = 91;
"Content-Type" = "application/json";
Date = "Fri, 18 Dec 2015 19:29:41 GMT";
Server = "Jetty(9.2.z-SNAPSHOT)";
} }
[Data]: 91 bytes
[Result]: SUCCESS: {
errors = (
);
results = (
{
columns = (
name
);
data = (
{
row = (
Bob
);
},
{
row = (
William
);
}
);
}
);
}
Edit
Making the same request without using Alamofire would look like this:
let cypherStatement = "CREATE (:Person {name: 'Bob'})-[:LIKES]->(pizza:Food {type: 'Pizza'})<-[:LIKES]-(:Person {name: 'William'}) WITH pizza MATCH (p:Person)-[:LIKES]->(pizz) RETURN p.name AS name"
let endpoint = "http://localhost:7474/db/data/transaction/commit"
let requestBody = [
"statements": [
[
"statement": cypherStatement
]
]
]
guard let url = NSURL(string: endpoint) else {
print("Error")
return true
}
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("application/json",forHTTPHeaderField: "Accept")
do{
let jsonData = try NSJSONSerialization.dataWithJSONObject(requestBody, options: .PrettyPrinted)
request.HTTPBody = jsonData
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
let result: NSDictionary
do {
result = try NSJSONSerialization.JSONObjectWithData(data!,
options: []) as! NSDictionary
} catch {
print("error trying to convert data to JSON")
return
}
print("\(result)")
})
task.resume()
} catch let error as NSError {
print("JSON serialization error")
return true
}

Swift Alamofire upload image in variable for rails API

So here is my problem, I must upload an image in my swift application to a server that use rails. I got almost everything set up, except that the rails api must receive the file data in a variable document[:file]
here is the function I use to encode my image with alamofire:
static func getDocumentCreateUploadData(parameters: [String : AnyObject], imageData: NSData) -> (uploadData:NSMutableData, contentType:String) {
let boundaryConstant = "NET-POST-boundary-\(arc4random())-\(arc4random())";
let contentType = "multipart/form-data;boundary="+boundaryConstant
let uploadData = NSMutableData()
// add image
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(imageData)
// add parameters
for (key, value) in parameters {
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return (uploadData, contentType)
}
And then I call my api with
var imageParameters = [
"documents": [
"documentable_type": "Profile",
"documentable_id": user.profile.id!
]
]
let data = Router.getDocumentCreateUploadData(imageParameters, imageData: imageData)
let urlRequest = Router.CreateDocument(contentType: data.contentType)
Alamofire.upload(urlRequest, data.uploadData).validate().responseSwiftyJSON({ (request, response, json, error) in
if error != nil {
...
What I would like to know is how can I encode the image so that it respect the api specification.
{
"documents" : {
"file": the_file,
"documentable_type": the_documentable_type,
"documentable_id": the_documentable_id
}
}
Is there a way to achieve this?
Thank in advance.
I simply misundertood the api, I didn't needed the root document in my upload call
All I needed to do was remove the document root but here is the way I did it :
let imageParameters = [
"documentable_type": "Comment",
"organization_id": organizationId,
"member_id": memberId,
"user_id": user.id
]
let uuid = NSUUID().UUIDString
composeBarView.enabled = false
ProgressHUDManager.uploadingStatus()
Alamofire.upload(
Router.CreateDocument,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data: imageData!, name: "file", fileName: "\(uuid).jpg", mimeType: "image/jpeg")
for (key, value) in imageParameters {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
},
encodingCompletion: { encodingResult in
// Handle result
}
)
The API Evolved so the code is new but I hope it can help