Post array of objects with Alamofire and SwiftyJSON
Asked Answered
N

4

6

I have an array of dictionaries that I am trying to post to Alamofire with the help of SwiftyJSON.

The api is set to take:

[
    {
        "imageUrl": "someimage3.jpg"
    },
    {
        "imageUrl": "someimage4.jpg"
    }
]

My array with image objects when printed out looks like this with the imageUrl key and image name for the value.

uploadedFiles = [
    [imageUrl: "someimage.jpg"],
    [imageUrl: "someimage2.jpg"]
]

I'm trying to convert the array of dictionaries into the format needed for the body. I'm not quite sure how to get them to be [String: AnyObject]

var body: [String: AnyObject] = [:]
let paramsJSON = JSON(uploadedFiles)
body = paramsJSON

alamofire post

Alamofire.request("\(BASE_URL)mainimages/\(someid)", method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseString { (response) in
        if response.result.error == nil {
            let status = response.response?.statusCode
            completion(true, status)
        } else {
            completion(false, nil)
            debugPrint(response.result.error as Any)
        }
    }
Neurology answered 26/4, 2018 at 5:59 Comment(6)
The API takes an array, so give it one.Eunuchoidism
Key name should be String type in uploadedFiles dictionaryMinica
show your code where you set the Alamofire request body.(ie params)Chromatic
Just updated the post request, thanks.Neurology
Please clarify: with "image objects" you are actually meaning URLs? Do you want to upload images as well? (if yes I would recommend a multipart request)Flower
No, just the urls. The images are already uploaded at this point.Neurology
C
3

You can done this by constructing manual request and call the Alamofire.request as below

var request = URLRequest(url: .......))
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")

//parameter array

let uploadedFiles = [
   [imageUrl: "someimage.jpg"],
   [imageUrl: "someimage2.jpg"]
]

request.httpBody = try! JSONSerialization.data(withJSONObject: uploadedFiles)

Alamofire.request(request).responseJSON { response in

    switch (response.result) {
    case .success:

        //success code here

    case .failure(let error):

        //failure code here
    }
}

If you can easily change the format in Sever side, ignore the above solution and changed as dictionary

[ "list_key" : [
       [imageUrl: "someimage.jpg"],
       [imageUrl: "someimage2.jpg"]
    ] 
 ]
Chromatic answered 26/4, 2018 at 6:39 Comment(7)
Mani, you probably made a typo: your suggested JSON is still an array respectively not valid JSON ;)Flower
@Flower Yes. I know. But I'm not setting Alamofire's params, instead i'm directly setting httpbody. whose said, Array of Dictinoary is not valid JSON?Chromatic
Well, your JSON is not exactly valid - it's just not a dictionary as you stated. It's a JSON Array of JSON Objects (Dictionaries). If you want to post some kind of object as JSON, it's best to use a JSON Object (aka Dictionary) as the root. If you want to post an array of some kind of objects, you can post an JSON Array of JSON Objects (as this kind of object) to the server. I think we agree :) – CouchDeveloper 5 mins ago editFlower
@Flower You can use the Foundation framework’s JSONSerialization class to convert JSON into Swift data types like Dictionary, Array, String, Number, and Bool.. see here developer.apple.com/swift/blog/?id=37 so the object don't need to be a dictionary for converting it into JSON, it may be any one of mentioned types.Chromatic
one more point. Ya this is right it's best to use a JSON Object (aka Dictionary) as the root, But at the same time, if root object is not Dictionary, we can't say that's not JSON. It's also JSON.Chromatic
I get this error *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (_SwiftValue)'Neurology
I also tried reformatted my api like your second suggestion. Api is fine but when passing in the body I get the same invalid JSON error. let body: [String: AnyObject] = [ "allImages": uploadedFiles as AnyObject ]Neurology
V
3

You can achieve using this method, It worked for me.

let payload = [["eventName": "Notifications","body":["version": "1.0","latitude": lat,"longitude":lon]]] as [[String : AnyObject]]

trackEventRequest(requestParams: payload, urlString: "https://xyz/youyURL")





func trackEventRequest(requestParams: [[String: AnyObject]], urlString: String) {

        let url = URL(string: urlString)
        var request = URLRequest(url: url!)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = try! JSONSerialization.data(withJSONObject: requestParams, options: [])

        Alamofire.request(reqeust).responseJSON { (response) in
            switch response.result {
            case .success:
                print(response.result.value)
                break
            case .failure:
                print(response.error)
                break
            }
        }
    }
Virago answered 15/9, 2018 at 11:7 Comment(0)
E
1

The API seems to take a JSON that has an array as the top level, not a dictionary, so converting your array to a dictionary is incorrect.

Just pass an array in!

SwiftyJSON's JSON conforms to ExpressibleByArrayLiteral, so you can just use an array literal:

let paramsJSON: JSON = [
    ["imageUrl": "someimage.jpg"],
    ["imageUrl": "someimage2.jpg"]
]

EDIT: I just realised that Alamofire's request method only accepts a [String: AnyObject]. This means that you need to do your own parameter encoding, demonstrated here.

Alternatively, create your own URLRequest, as shown in this post:

var request = URLRequest(url: someURL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = paramsJSON.rawData()
Alamofire.request(request)
Eunuchoidism answered 26/4, 2018 at 6:7 Comment(2)
Sorry I may have not been clear, I'm not trying to convert it to a dictionary, that is what I have now. Just get it into something I can pass to alamofire. I tried your array and get the error "Extra argument 'method' in call"Neurology
This does solve the problem of not being able to upload my array with Alamofire. I'm still having an issue getting my array of dictionaries into the correct JSON format. let paramsJSON: JSON = JSON(uploadedFiles) gives me unknown. uploadedFiles printed out looks like this: [MyApp.NoteImage(imageUrl: "someimage.png”), MyApp.NoteImage(imageUrl: "someimage2.png")]Neurology
N
0

I reformatted my API like Mani suggested to make it easier to give Alamofire what is needed. It's now looking for this:

{
    "allImages" : [
        {
            "imageUrl": "someimage5.jpg"
        },
        {
            "imageUrl": "someimage6.jpg"
        }
    ]
}

I also had to reformat my array like the code below to get the JSON errors to go away.

var newUploadFilesArray = [AnyObject]()
    for item in uploadedFiles {
        let singleImageDict = ["imageUrl" : item.imageUrl]
        newUploadFilesArray.append(singleImageDict as AnyObject)
    }

    let body: [String: AnyObject] = [
        "allImages": newUploadFilesArray as AnyObject
    ]

    Alamofire.request("\(BASE_URL)mainimages/\(mainId)", method: .post, parameters: body, encoding: JSONEncoding.default, headers: header).responseString { (response) in
        if response.result.error == nil {
            let status = response.response?.statusCode
            completion(true, status)
        } else {
            completion(false, nil)
            debugPrint(response.result.error as Any)
        }
    }
Neurology answered 4/5, 2018 at 4:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.