0

I need to to send a list of objects to an end point. the required type has the following keys

{
  id: Int;
  all: Bool;
  batch: Bool;
  chapter: Bool;
  myNetwork: Bool;
  categoryId: Int;
}

the api expected a list of the above object. i generated a list using Parameter type of Alamofire like this.

[
    ["chapter": "true", "myNetwork": "false", "id": "3", "categoryId": "1", "memberId": "13", "batch": "true", "all": "true"], 
    ["categoryId": "2", "batch": "false", "myNetwork": "true", "all": "true", "id": "891", "memberId": "13", "chapter": "true"], 
    ["batch": "false", "memberId": "13", "categoryId": "3", "all": "false", "id": "1779", "myNetwork": "false", "chapter": "false"], 
    ["batch": "true", "id": "2667", "all": "false", "chapter": "true", "memberId": "13", "categoryId": "4", "myNetwork": "false"]
]

but it shows error

Cannot convert value of type '[[String : Any]]' to expected argument type 'Parameters?' (aka 'Optional>')

How can i sent this list of objects to an API using Alamofire ? the code that dispatch request

Alamofire.request("(APIManager.url)/Privacy/Update", method: .post, parameters: params, encoding: JSONEncoding.default, headers: APIManager.headers)

2

3 Answers 3

1

your parameters should be like this

["key": "value", "key": "value"]

which is a dictionary, what you're using is an array of dictionary that's why you're getting an error

Sign up to request clarification or add additional context in comments.

1 Comment

I understand why that error pop up, am asking how to send a list of objects using alamofire
1

You can use this open source class JSONSerializer from https://github.com/peheje/JsonSerializerSwift/blob/master/JsonSerializerSwift/JsonSerializer.swift

I have made some changes in this class to append an array of objects with key in existing JSON

import Foundation

 /// Handles Convertion from instances of objects to JSON strings. Also helps with casting strings of JSON to Arrays or Dictionaries.
open class JSONSerializer {

/**
Errors that indicates failures of JSONSerialization
- JsonIsNotDictionary:  -
- JsonIsNotArray:           -
- JsonIsNotValid:           -
*/
public enum JSONSerializerError: Error {
    case jsonIsNotDictionary
    case jsonIsNotArray
    case jsonIsNotValid
}

//http://stackoverflow.com/questions/30480672/how-to-convert-a-json-string-to-a-dictionary
/**
Tries to convert a JSON string to a NSDictionary. NSDictionary can be easier to work with, and supports string bracket referencing. E.g. personDictionary["name"].
- parameter jsonString: JSON string to be converted to a NSDictionary.
- throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotDictionary. JsonIsNotDictionary will typically be thrown if you try to parse an array of JSON objects.
- returns: A NSDictionary representation of the JSON string.
*/
open static func toDictionary(_ jsonString: String) throws -> NSDictionary {
    if let dictionary = try jsonToAnyObject(jsonString) as? NSDictionary {
        return dictionary
    } else {
        throw JSONSerializerError.jsonIsNotDictionary
    }
}

/**
Tries to convert a JSON string to a NSArray. NSArrays can be iterated and each item in the array can be converted to a NSDictionary.
- parameter jsonString: The JSON string to be converted to an NSArray
- throws: Throws error of type JSONSerializerError. Either JsonIsNotValid or JsonIsNotArray. JsonIsNotArray will typically be thrown if you try to parse a single JSON object.
- returns: NSArray representation of the JSON objects.
*/
open static func toArray(_ jsonString: String) throws -> NSArray {
    if let array = try jsonToAnyObject(jsonString) as? NSArray {
        return array
    } else {
        throw JSONSerializerError.jsonIsNotArray
    }
}

/**
Tries to convert a JSON string to AnyObject. AnyObject can then be casted to either NSDictionary or NSArray.
- parameter jsonString: JSON string to be converted to AnyObject
- throws: Throws error of type JSONSerializerError.
- returns: Returns the JSON string as AnyObject
*/
fileprivate static func jsonToAnyObject(_ jsonString: String) throws -> Any? {
    var any: Any?

    if let data = jsonString.data(using: String.Encoding.utf8) {
        do {
            any = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
        }
        catch let error as NSError {
            let sError = String(describing: error)
            NSLog(sError)
            throw JSONSerializerError.jsonIsNotValid
        }
    }
    return any
}

/**
Generates the JSON representation given any custom object of any custom class. Inherited properties will also be represented.
- parameter object: The instantiation of any custom class to be represented as JSON.
- returns: A string JSON representation of the object.
*/
open static func toJson(_ object: Any, prettify: Bool = false) -> String {
    var json = ""
    if (!(object is Array<Any>)) {
        json += "{"
    }
    let mirror = Mirror(reflecting: object)

    var children = [(label: String?, value: Any)]()

    if let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children) {
        children += mirrorChildrenCollection
    }
    else {
        let mirrorIndexCollection = AnyCollection(mirror.children)
        children += mirrorIndexCollection
    }

    var currentMirror = mirror
    while let superclassChildren = currentMirror.superclassMirror?.children {
        let randomCollection = AnyRandomAccessCollection(superclassChildren)!
        children += randomCollection
        currentMirror = currentMirror.superclassMirror!
    }

    var filteredChildren = [(label: String?, value: Any)]()

    for (optionalPropertyName, value) in children {

        if let optionalPropertyName = optionalPropertyName {

            if !optionalPropertyName.contains("notMapped_") {
                filteredChildren.append((optionalPropertyName, value))
            }

        }
        else {
            filteredChildren.append((nil, value))
        }
    }

    var skip = false
    let size = filteredChildren.count
    var index = 0

    var first = true

    for (optionalPropertyName, value) in filteredChildren {
        skip = false

        let propertyName = optionalPropertyName
        let property = Mirror(reflecting: value)

        var handledValue = String()

        if propertyName != nil && propertyName == "some" && property.displayStyle == Mirror.DisplayStyle.struct {
            handledValue = toJson(value)
            skip = true
        }
        else if (value is Int ||
                 value is Int32 ||
                 value is Int64 ||
                 value is Double ||
                 value is Float ||
                 value is Bool) && property.displayStyle != Mirror.DisplayStyle.optional {
            handledValue = String(describing: value)
        }
        else if let array = value as? [Int?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Double?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Float?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Bool?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? "\"\(value!)\"" : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += "\"\(value)\""
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? NSArray {
            handledValue += "["
            for (index, value) in array.enumerated() {
                if !(value is Int) &&
                   !(value is Int32) &&
                   !(value is Int64) &&
                   !(value is Double) && !(value is Float) && !(value is Bool) && !(value is String) {
                    handledValue += toJson(value)
                }
                else {
                    handledValue += "\(value)"
                }
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if property.displayStyle == Mirror.DisplayStyle.class ||
            property.displayStyle == Mirror.DisplayStyle.struct ||
            String(describing: value).contains("#") {
            handledValue = toJson(value)
        }
        else if property.displayStyle == Mirror.DisplayStyle.optional {
            let str = String(describing: value)
            if str != "nil" {
                // Some optional values cannot be unpacked if type is "Any"
                // We remove the "Optional(" and last ")" from the value by string manipulation
                var d = String(str).dropFirst(9)
                d = d.dropLast(1)
                handledValue = String(d)
            } else {
                handledValue = "null"
            }
        }
        else {
            handledValue = String(describing: value) != "nil" ? "\"\(value)\"" : "null"
        }

        if !skip {

            // if optional propertyName is populated we'll use it
            if let propertyName = propertyName {
                json += "\"\(propertyName)\": \(handledValue)" + (index < size-1 ? ", " : "")
            }
            // if not then we have a member an array
            else {
                // if it's the first member we need to prepend ]
                if first {
                    json += "["
                    first = false
                }
                // if it's not the last we need a comma. if it is the last we need to close ]
                json += "\(handledValue)" + (index < size-1 ? ", " : "]")
            }

        } else {
            json = "\(handledValue)" + (index < size-1 ? ", " : "")
        }

        index += 1
    }

    if !skip {
        if (!(object is Array<Any>)) {
            json += "}"
        }
    }

    if prettify {
       let jsonData = json.data(using: String.Encoding.utf8)!
       let jsonObject = try! JSONSerialization.jsonObject(with: jsonData, options: [])
       let prettyJsonData = try! JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
       json = NSString(data: prettyJsonData, encoding: String.Encoding.utf8.rawValue)! as String
    }

    return json
}
/**
 Generates the JSON representation given any custom object of any custom class. Inherited properties will also be represented.
 - parameter object:    The instantiation of any custom class to be represented as JSON.
 - returns: A string JSON representation of the object.
 */
open static func toJson(key: String, _ object: Any, existingJson: String = "", prettify: Bool = false) -> String {
    var json = ""
    if (!(object is Array<Any>)) {
        json += "{ "
    }
    let mirror = Mirror(reflecting: object)

    var children = [(label: String?, value: Any)]()

    if let mirrorChildrenCollection = AnyRandomAccessCollection(mirror.children) {
        children += mirrorChildrenCollection
    }
    else {
        let mirrorIndexCollection = AnyCollection(mirror.children)
        children += mirrorIndexCollection
    }

    var currentMirror = mirror
    while let superclassChildren = currentMirror.superclassMirror?.children {
        let randomCollection = AnyRandomAccessCollection(superclassChildren)!
        children += randomCollection
        currentMirror = currentMirror.superclassMirror!
    }

    var filteredChildren = [(label: String?, value: Any)]()

    for (optionalPropertyName, value) in children {

        if let optionalPropertyName = optionalPropertyName {

            if !optionalPropertyName.contains("notMapped_") {
                filteredChildren.append((optionalPropertyName, value))
            }

        }
        else {
            filteredChildren.append((nil, value))
        }
    }

    var skip = false
    let size = filteredChildren.count
    var index = 0

    var first = true

    for (optionalPropertyName, value) in filteredChildren {
        skip = false

        let propertyName = optionalPropertyName
        let property = Mirror(reflecting: value)

        var handledValue = String()

        if propertyName != nil && propertyName == "some" && property.displayStyle == Mirror.DisplayStyle.struct {
            handledValue = toJson(value)
            skip = true
        }
        else if (value is Int ||
            value is Int32 ||
            value is Int64 ||
            value is Double ||
            value is Float ||
            value is Bool) && property.displayStyle != Mirror.DisplayStyle.optional {
            handledValue = String(describing: value)
        }
        else if let array = value as? [Int?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Double?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Float?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [Bool?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? String(value!) : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String?] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += value != nil ? "\"\(value!)\"" : "null"
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? [String] {
            handledValue += "["
            for (index, value) in array.enumerated() {
                handledValue += "\"\(value)\""
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if let array = value as? NSArray {
            handledValue += "["
            for (index, value) in array.enumerated() {
                if !(value is Int) &&
                    !(value is Int32) &&
                    !(value is Int64) &&
                    !(value is Double) && !(value is Float) && !(value is Bool) && !(value is String) {
                    handledValue += toJson(value)
                }
                else {
                    handledValue += "\(value)"
                }
                handledValue += (index < array.count-1 ? ", " : "")
            }
            handledValue += "]"
        }
        else if property.displayStyle == Mirror.DisplayStyle.class ||
            property.displayStyle == Mirror.DisplayStyle.struct ||
            String(describing: value).contains("#") {
            handledValue = toJson(value)
        }
        else if property.displayStyle == Mirror.DisplayStyle.optional {
            let str = String(describing: value)
            if str != "nil" {
                // Some optional values cannot be unpacked if type is "Any"
                // We remove the "Optional(" and last ")" from the value by string manipulation
                var d = String(str).dropFirst(9)
                d = d.dropLast(1)
                handledValue = String(d)
            } else {
                handledValue = "null"
            }
        }
        else {
            handledValue = String(describing: value) != "nil" ? "\"\(value)\"" : "null"
        }

        if !skip {

            // if optional propertyName is populated we'll use it
            if let propertyName = propertyName {
                json += "\"\(propertyName)\": \(handledValue)" + (index < size-1 ? ", " : "")
            }
                // if not then we have a member an array
            else {
                // if it's the first member we need to prepend ]
                if first {
                    json += "["
                    first = false
                }
                // if it's not the last we need a comma. if it is the last we need to close ]
                json += "\(handledValue)" + (index < size-1 ? ", " : "]")
            }

        } else {
            json = "\(handledValue)" + (index < size-1 ? ", " : "")
        }

        index += 1
    }

    if !skip {
        if (!(object is Array<Any>)) {
            json += "}"
        }
    }

    if !existingJson.isEmpty {
        var JSON = existingJson
        JSON.removeLast()
        JSON = JSON + ", \"\(key)\": " + json + " }"
        if prettify {
            return prettyJson(json: JSON)
        }
        return JSON
    } else if existingJson.isEmpty {
        if prettify {
            return prettyJson(json: "{ \"\(key)\": " + json + " }")
        }
        return "{ \"\(key)\": " + json + " }"
    }
    return prettyJson(json: json)
}

private static func prettyJson(json: String) -> String {
    let jsonData = json.data(using: String.Encoding.utf8)!
    let jsonObject = try! JSONSerialization.jsonObject(with: jsonData, options: [])
    let prettyJsonData = try! JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
    return NSString(data: prettyJsonData, encoding: String.Encoding.utf8.rawValue)! as String
}

}

And here is the code to use this class

let params = [ "some key": "some value"]
     if let theJSONData = try? JSONSerialization.data(withJSONObject: params, options: []) {
         let theJSONText = String(data: theJSONData, encoding: .ascii)
         let json = JSONSerializer.toJson(key: "Products", Cart.sharedInstance.products, existingJson: theJSONText!, prettify: true)
         print("JSON string = \(json)")
         let finalParams = json.convertToDictionary()
         // pass finalParams as Alamofire param
}

Replace Cart.sharedInstance.products with your array of objects and Products with your key.

You can see the overloaded methods as per your need.

Hope you get the desired result.

1 Comment

this still upload dictionary, not array
0

As the error says , it's expecting a Dictionary<String, Any> but you are passing [[String : Any]] a.k.a Array<Dictionary<String,Any>>.

You might want to change that and add your array of dictionary (which is the data you want to send) to the Any part of Dictionary<String, Any>, assign it any key and send it.

What you can do is -

["data" : [
["chapter": "true", "myNetwork": "false", "id": "3", "categoryId": "1", "memberId": "13", "batch": "true", "all": "true"], 
["categoryId": "2", "batch": "false", "myNetwork": "true", "all": "true", "id": "891", "memberId": "13", "chapter": "true"], 
["batch": "false", "memberId": "13", "categoryId": "3", "all": "false", "id": "1779", "myNetwork": "false", "chapter": "false"], 
["batch": "true", "id": "2667", "all": "false", "chapter": "true", "memberId": "13", "categoryId": "4", "myNetwork": "false"]
]]

So here data will be your key and it's value will be what you want to send

NOTE - You might want to change the server code accordingly and accept a dictionary at top level

2 Comments

That works only if the server is expecting a Dictionary at top level.
Why don't you go for URLSession then ? If all you want to do is send some data to the server then why use Alamofire in the first place

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.