【问题标题】:swift: cast incoming json array to dictionary and objectswift:将传入的 json 数组转换为字典和对象
【发布时间】:2014-10-18 18:34:23
【问题描述】:

我正在玩弄/学习 Swift 和 JSON atm,但在正确转换我的响应时遇到了问题。

所以,我想要实现的是通过 Alamofire 请求显示“帖子”列表。我在显示“第一级”json 项目(如 post-ID 或“消息”)时没有问题,但是当涉及到作者数组时,我有点迷路了。

json 响应以没有名称的数组形式出现,因此第一个 [

[
-{
__v: 1,
_id: "54428691a728c80424166ffb",
createDate: "2014-10-18T17:26:15.317Z",
message: "shshshshshshshhshshs",
-author: [
-{
_id: "54428691a728c80424166ffa",
userId: "543270679de5893d1acea11e",
userName: "foo"
}
]
} 

这是我对应的VC:

    Alamofire.request(.GET, "\(CurrentConfiguration.serverURL)/api/posts/\(CurrentConfiguration.currentUser.id)/newsfeed/\(CurrentConfiguration.currentMode)",encoding:.JSON)
            .validate()
            .responseJSON {(request, response, jsonData, error) in

                let JSON = jsonData as? NSArray
                self.loadPosts(JSON!)
        }

        tableView.delegate = self

        tableView.dataSource = self

    }

    func loadPosts(posts:NSArray) {
        for post in posts {
            let id = post["_id"]! as NSString!
            let message = post["message"]! as NSString!

            var authorArray = post["author"]! as? [Author]!
            println(authorArray)

            var author:Author = Author()
            author.userName = "TEST ME"

            var postObj:Post = Post()
            postObj.id = id
            postObj.message = message
            postObj.author = author
            uppDatesCollection.append(postObj)
        }
        println(self.uppDatesCollection.count)
        dispatch_async(dispatch_get_main_queue()) {
            self.tableView.reloadData()
        }
    }

我的帖子模型

class Post {
    var id:String!
    var message:String!
    var createDate: NSDate!

    var author:Array<Author>!

    init () {

    }
} 

和作者

class Author {
        var id:String?
        var userId:String?
        var userName:String?

        init () {
    }

这里最好的方法是什么?您是否应该将返回的数组重新转换为字典,然后通过 .valueforkey 访问它?您是否以某种方式遍历数组以获取这些内容?

显然你不能说 author.name = authorArray[3] as String

【问题讨论】:

    标签: ios json swift ios8 alamofire


    【解决方案1】:

    假设你有这样的Post 类:

    class Post : Printable {
        var identifier:String!
        var message:String!
        var createDate: NSDate!
        var authors:[Author]!
    
        var description: String { return "<Post; identifier = \(identifier); message = \(message); createDate = \(createDate); authors = \(authors)" }
    }
    

    您的 JSON 中只有一个作者,但鉴于它似乎是 JSON 中的一个数组,我假设它也应该是对象模型中的一个数组,如上所示。 Author 类可以这样定义:

    class Author : Printable {
        var identifier:String!
        var userId:String!
        var userName:String!
    
        var description: String { return "<Author; identifier = \(identifier); userId = \(userId); userName = \(userName)>" }
    }
    

    我不知道为什么你隐含地解包了一些选项(使用! 定义)而其他没有(使用? 定义),所以我只是将它们全部隐含解包。根据您的业务规则进行调整。

    另外,假设您的 JSON 看起来像这样(我不太确定您的问题中 JSON 中的 - 是什么,所以我清理了它并添加了第二位作者):

    [
        {
            "__v": 1,
            "_id": "54428691a728c80424166ffb",
            "createDate": "2014-10-18T17:26:15.317Z",
            "message": "shshshshshshshhshshs",
            "author": [
                {
                    "_id": "54428691a728c80424166ffa",
                    "userId": "543270679de5893d1acea11e",
                    "userName": "foo"
                },
                {
                    "_id": "8434059834590834590834fa",
                    "userId": "345903459034594355cea11e",
                    "userName": "bar"
                }
            ]
        }
    ]
    

    那么解析它的例程可能如下所示:

    func loadPosts(postsJSON: NSArray) {
        var posts = [Post]()
    
        for postDictionary in postsJSON {
            let post = Post()
            let createDateString = postDictionary["createDate"] as String
            post.message = postDictionary["message"] as String
            post.identifier = postDictionary["_id"] as String
            post.createDate = createDateString.rfc3339Date()
    
            if let authorsArray = postDictionary["author"] as NSArray? {
                var authors = [Author]()
                for authorDictionary in authorsArray {
                    let author = Author()
                    author.userId = authorDictionary["userId"] as String
                    author.userName = authorDictionary["userName"] as String
                    author.identifier = authorDictionary["_id"] as String
                    authors.append(author)
                }
                post.authors = authors
            }
    
            posts.append(post)
        }
    
        // obviously, do something with `posts` array here, either setting some class var, return it, whatever
    }
    

    这是我从StringNSDate 的转换例程:

    extension String {
    
        /// Get NSDate from RFC 3339/ISO 8601 string representation of the date.
        ///
        /// For more information, see:
        ///
        /// https://developer.apple.com/library/ios/qa/qa1480/_index.html
        ///
        /// :returns: Return date from RFC 3339 string representation
    
        func rfc3339Date() -> NSDate? {
            let formatter = NSDateFormatter()
    
            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
            formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
            formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    
            return formatter.dateFromString(self)
        }
    }
    

    【讨论】:

    • 非常感谢您的回答!有没有更通用的方法来做到这一点,无论是板载的还是基于库的?通过迭代数组(我很乐意实现)来做到这一点,理论上我可以最终得到像 8x 嵌套的函数,这对我来说听起来很丑。
    • 您当然可以按照这种方式做一些事情,但是如果没有看到一个展示此 JSON 的全部丰富性的示例,就很难说。您可能想在完全数据驱动和更实用的东西之间取得平衡。也许试一试,让我们知道你的情况。如果经过您的善意努力,您仍有疑问,请在此处发布新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多