将JSON数组反序列化为Swift对象数组

时间:2016-05-10 21:51:33

标签: ios json swift swift2

我是Swift的新手,我无法弄清楚如何将JSON数组反序列化为Swift对象数组。我能够将单个JSON用户反序列化为Swift用户对象,但不确定如何使用JSON用户数组。

这是我的User.swift类:

class User {
    var id: Int
    var firstName: String?
    var lastName: String?
    var email: String
    var password: String?

    init (){
        id = 0
        email = ""
    }

    init(user: NSDictionary) {
        id = (user["id"] as? Int)!
        email = (user["email"] as? String)!

        if let firstName = user["first_name"] {
            self.firstName = firstName as? String
        }

        if let lastName = user["last_name"] {
            self.lastName = lastName as? String
        }

        if let password = user["password"] {
            self.password = password as? String
        }
     }
}

这是我尝试反序列化JSON的课程:

//single user works.
Alamofire.request(.GET, muURL/user)
         .responseJSON { response in
                if let user = response.result.value {
                    var swiftUser = User(user: user as! NSDictionary)
                }
          }

//array of users -- not sure how to do it. Do I need to loop?
Alamofire.request(.GET, muURL/users)
         .responseJSON { response in
                if let users = response.result.value {
                    var swiftUsers = //how to get [swiftUsers]?
                }
          }

4 个答案:

答案 0 :(得分:2)

最好的方法是使用Alamofire提供的通用响应对象序列化,这是一个例子:

1)在您的API管理器或单独的文件中添加扩展程序

    public protocol ResponseObjectSerializable {
        init?(response: NSHTTPURLResponse, representation: AnyObject)
    }

    extension Request {
        public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self {
            let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in
                guard error == nil else { return .Failure(error!) }

                let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
                let result = JSONResponseSerializer.serializeResponse(request, response, data, error)

                switch result {
                case .Success(let value):
                    if let
                        response = response,
                        responseObject = T(response: response, representation: value)
                    {
                        return .Success(responseObject)
                    } else {
                        let failureReason = "JSON could not be serialized into response object: \(value)"
                        let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
                        return .Failure(error)
                    }
                case .Failure(let error):
                    return .Failure(error)
                }
            }

            return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
        }
    }

public protocol ResponseCollectionSerializable {
    static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [Self]
}

extension Alamofire.Request {
    public func responseCollection<T: ResponseCollectionSerializable>(completionHandler: Response<[T], NSError> -> Void) -> Self {
        let responseSerializer = ResponseSerializer<[T], NSError> { request, response, data, error in
            guard error == nil else { return .Failure(error!) }

            let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
            let result = JSONSerializer.serializeResponse(request, response, data, error)

            switch result {
            case .Success(let value):
                if let response = response {
                    return .Success(T.collection(response: response, representation: value))
                } else {
                    let failureReason = "Response collection could not be serialized due to nil response"
                    let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
                    return .Failure(error)
                }
            case .Failure(let error):
                return .Failure(error)
            }
        }

        return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
    }
}

2)更新你的模型对象:

final class User: ResponseObjectSerializable, ResponseCollectionSerializable {
    let username: String
    let name: String

    init?(response: NSHTTPURLResponse, representation: AnyObject) {
        self.username = response.URL!.lastPathComponent!
        self.name = representation.valueForKeyPath("name") as! String
    }

    static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [User] {
        var users: [User] = []

        if let representation = representation as? [[String: AnyObject]] {
            for userRepresentation in representation {
                if let user = User(response: response, representation: userRepresentation) {
                    users.append(user)
                }
            }
        }

        return users
    }
}

3)然后你可以这样使用它:

Alamofire.request(.GET, "http://example.com/users")
         .responseCollection { (response: Response<[User], NSError>) in
             debugPrint(response)
         }

来源:Generic Response Object Serialization

有用的链接:Alamofire JSON Serialization of Objects and Collections

答案 1 :(得分:2)

由于您使用Alamofire提出请求,为什么您没有机会Hearst-DD ObjectMapper它有Alamofire扩展AlamofireObjectMapper。我认为这会节省你的时间!

答案 2 :(得分:1)

我会遍历它们然后将每个用户添加到一个数组(最好是VC的属性而不是实例变量),但这是一个例子。

    Alamofire.request(.GET, "YourURL/users")
        .responseJSON { response in

            if let users = response.result.value {

                for user in users {

                    var swiftUser = User(user: user as! NSDictionary)

                    //should ideally be a property of the VC
                    var userArray : [User]

                    userArray.append(swiftUser)
                }
            }
    }

答案 3 :(得分:1)

您也可以尝试EVReflection https://github.com/evermeer/EVReflection 它更简单,即解析JSON(从EVReflection链接获取的代码片段):

let json:String = "{
    \"id\": 24, 
    \"name\": \"Bob Jefferson\",
    \"friends\": [{
        \"id\": 29, 
        \"name\": 
        \"Jen Jackson\"}]}"

你可以使用这个类:

class User: EVObject {
    var id: Int = 0
    var name: String = ""
    var friends: [User]? = []
}

以这种方式:

let user = User(json: json)