Отправить массив объектов в alamofire - PullRequest
0 голосов
/ 24 мая 2019

Мне нужно отправить список объектов в конечную точку.требуемый тип имеет следующие ключи

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

API ожидает список вышеуказанного объекта.я сгенерировал список, используя тип параметра Alamofire, как это.

[
    ["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"]
]

, но он показывает ошибку

Невозможно преобразовать значение типа '[[String: Any]]' в ожидаемоеТип аргумента 'Параметры?'(иначе 'Необязательно>')

Как я могу отправить этот список объектов в API, используя Alamofire?код, который отправляет запрос

Alamofire.request ("(APIManager.url) / Privacy / Update", метод: .post, параметры: params, кодировка: JSONEncoding.default, заголовки: APIManager.headers)

Ответы [ 4 ]

1 голос
/ 26 мая 2019

Вы можете использовать этот класс с открытым исходным кодом JSONSerializer из https://github.com/peheje/JsonSerializerSwift/blob/master/JsonSerializerSwift/JsonSerializer.swift

Я внес некоторые изменения в этот класс, чтобы добавить массив объектов с ключом в существующие 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
}

}

А вот код для использования этого класса

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
}

Замените Cart.sharedInstance.products на ваш массив объектов и Products с вашим ключом.

Вы можете увидеть перегруженные методы в соответствии с вашими потребностями.

Надеюсь, вы получите желаемый результат.

0 голосов
/ 24 мая 2019

Как говорит ошибка, ожидается, что Dictionary<String, Any>, но вы передаете [[String : Any]] a.k.a Array<Dictionary<String,Any>>.

Возможно, вы захотите изменить это и добавить массив словаря (который представляет собой данные, которые вы хотите отправить) в Any часть Dictionary<String, Any>, назначьте ему любую клавишу и отправь.

Что вы можете сделать, это -

["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"]
]]

Так что здесь data будет вашим ключом , и это значение будет тем, что вы хотите отправить

ПРИМЕЧАНИЕ - Вы можете изменить код сервера соответствующим образом и принять словарь на верхнем уровне

0 голосов
/ 24 мая 2019

преобразовать ваш массив в строку JSON. это лучший способ отправить список объектов при использовании Alamofire

var JSONBinData: String = ""

if let theJSONData = try?  JSONSerialization.data(
                withJSONObject: binData,
                options: .prettyPrinted
                ),
                let theJSONText = String(data: theJSONData,
                                         encoding: String.Encoding.ascii) {
                print("JSON string = \n\(theJSONText)")
                JSONBinData = theJSONText
            }
0 голосов
/ 24 мая 2019

ваши параметры должны быть такими:

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

, который является словарем, который вы используете, это массив словарей, поэтому вы получаете ошибку

...