2014-10-18 111 views
2

我忙着/学习Swift和JSON atm,并且正确地解决了我的响应问题。swift:将传入的json数组转换为字典和对象

所以,我想实现的是通过Alamofire请求显示“帖子”列表。我没有任何问题显示“第一级”json项目,如后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() { 
    } 

这里最好的方法是什么?你应该重新返回Array作为一个字典,然后通过.valueforkey访问它?你以某种方式遍历数组来获取这些东西吗?

显然,你不能说 author.name = authorArray [3]作为字符串

回答

2

比方说,你有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) 
    } 
} 
+0

非常感谢您的回答!有没有更通用的方法来做到这一点,无论是板载或基于库?通过迭代Array(我很乐意实现),理论上我可以用8x嵌套来实现对我来说听起来相当丑陋的函数。 – longbow 2014-10-18 21:14:30

+0

当然,你可以在这方面做些事情,但是如果没有看到一个能够证明这个JSON丰富的例子,很难说。您可能希望在完全数据驱动和实用性之间取得平衡。也许放弃一下吧,让我们知道你是怎么走的。如果经过您的诚意努力,您仍然有疑问,请在s.o上发布新问题。 – Rob 2014-10-18 21:26:45