如何在 Swift 4 的 NSObject 类中初始化 json 内的数组?

Posted

技术标签:

【中文标题】如何在 Swift 4 的 NSObject 类中初始化 json 内的数组?【英文标题】:How to initialize array inside json in a NSObject class in Swift 4? 【发布时间】:2018-02-09 08:21:12 【问题描述】:

我有一个这样的 JSON 格式的 API 响应:


"item": [
        
            "item_id": 484,
            "user_id": 123,
            "lucky_number": -1,
            "liked_user": [
                
                    "user_id": 2
                ,
                
                    "user_id": 1
                
            ],
            "modified_time": "0000-09-19 10:24:02"
        

    ]

我知道如何在上面的结果中解析item_iduser_id 和其他人的结果。但是如何在上面的响应中获取liked_user 的结果,这是一个数组?

现在我的 NSObject 类看起来像这样:

class Item : NSObject 
    var itemtId :Int
    var userId : Int
    var luckyNumber : Int
    var itemCreatedAt : String

    init?(dict: [String :JSON]) 
        self.itemId = dict["item_id"]?.int ?? 0
        self.userId = dict["user_id"]?.int ?? 0
        self.luckyNumber = dict["lucky_number"]?.int ?? 0
        self.itemCreatedAt = dict["modified_time"]?.string ?? ""
    


然后在我进行 API 调用之后,我会像这样解析对此类的响应:

var items = [Item]()

My ApiCall success ....  

    let json = JSON(result) // this is SwiftyJson
    guard let itemArr = json["item"].array else
        return
    

    for item in itemArr 
        if let item = item.dictionary,let feed = Item.init(dict: item)
            self.items.append(feed)
    


所以我的问题是,在这种情况下,我如何解析liked_user 中的数据并将其存储在我的Item 类中?

【问题讨论】:

【参考方案1】:

使用您给定的代码,解决方案是在类中创建一个数组likedUserIDs

class Item : NSObject 
    var itemtId :Int
    var userId : Int
    var luckyNumber : Int
    var itemCreatedAt : String
    var likedUserIDs = [Int]()

    init?(dict: [String :JSON]) 
        self.itemId = dict["item_id"]?.int ?? 0
        self.userId = dict["user_id"]?.int ?? 0
        self.luckyNumber = dict["lucky_number"]?.int ?? 0
        self.itemCreatedAt = dict["modified_time"]?.string ?? ""
        if let likedUsers = dict["liked_user"]?.array 
           for likedUser in likedUsers 
               likedUserIDs.append(likedUser["user_id"].intValue)
           
        
    


但是在 Swift 4 中,我推荐使用 (De)Codable 协议并使用结构来解析 JSON。

SwiftyJSON 不再需要(不再需要)。

struct Root : Decodable 
    let item : [Item]


struct Item : Decodable 
    let itemId :Int
    let userId : Int
    let luckyNumber : Int
    let itemCreatedAt : String
    let likedUsers : [LikedUser]

    private enum CodingKeys : String, CodingKey 
        case itemId = "item_id"
        case userId = "user_id"
        case luckyNumber = "lucky_number"
        case itemCreatedAt = "modified_time"
        case likedUsers = "liked_user"
    

    struct LikedUser : Decodable 
        let userID : Int
        private enum CodingKeys : String, CodingKey  case userID = "user_id" 
    

并将原始 JSON 解码为 Data 对象

do 
    let result = try decoder.decode(Root.self, from: data)
    print(result)
 catch 
    print("error: ", error)

【讨论】:

您是否有意省略了init(from:) 的实现?据我了解,一旦您为CodingKey 提供自定义键,您就应该/必须自己实现init(from:)。还是我错过了什么? 编码键用于将 snake_cased 键更改为 camelCase。不需要init(from:【参考方案2】:

我认为liked_user 的结果是一个包含两个Json 对象的数组。 下面的代码块将对您有所帮助。

let liked_users = json["liked_user"].array
for liked_user in liked_users 
    let user_id = liked_user["user_id"].int

您可以将 user_id 保存到 Item 类中的数组中。

class Item : NSObject 
    var itemId :Int
    var userId : Int
    var luckyNumber : Int
    var itemCreatedAt : String
    var useridArray: [Int] = []

    init?(dict: [String :JSON]) 
        self.itemId = dict["item_id"]?.int ?? 0
        self.userId = dict["user_id"]?.int ?? 0
        self.luckyNumber = dict["lucky_number"]?.int ?? 0
        self.itemCreatedAt = dict["modified_time"]?.string ?? ""
        if let liked_users = dict["liked_user"]?.array  
            for liked_user in liked_users 
                if let userid = liked_user["user_id"]?.int 
                    useridArray.append(userid)
                
            
        
    


【讨论】:

你能告诉我如何将我的 userIdArray 的数组存储在我的 Item 类中吗?因为这就是我问这个问题的原因 类没有编译。 @ken 我希望这对你有帮助。 不,这是一个class has not initialized properties 错误,但在添加初始化行后,错误消失了。但是,您应该在声明行中初始化数组。 请学习使用mapflatMapuserIdArray = dict["liked_user"]?.arrayValue.flatMap $0["user_id"]?.int 【参考方案3】:

在您的 Item 对象中创建一个 likeUsersArray 变量,然后以这种方式解析字典数组:

 class Item : NSObject 
    var itemtId :Int
    var userId : Int
    var luckyNumber : Int
    var itemCreatedAt : String
    var likedUsersArray: [Int] = []

    init?(dict: [String :JSON]) 
        self.itemId = dict["item_id"]?.int ?? 0
        self.userId = dict["user_id"]?.int ?? 0
        self.luckyNumber = dict["lucky_number"]?.int ?? 0
        self.itemCreatedAt = dict["modified_time"]?.string ?? ""
        for likedUserDict in dict["liked_user"]?.array 
            if let dict = likedUserDict?.dictionary, let likedUserId = dict["user_id"].int                     
                self.likedUsersArray.append(likedUserId)
            
        
    

【讨论】:

cannot subsript of value of a type '[JSON]' with index of type 'String'.Bro 我收到这个错误 Cast from '[JSON]?' to unrelated type '[String : Any]' always failsValue of tuple type '(key: String, value: Any)' has no member 'subscript' 我现在知道了 尝试将 likeUserDict 转换为 SwiftyJson 字典,我再次编辑了我的答案。 Value of optional type '[JSON]?' not unwrapped; did you mean to use '!' or '?'? 有很多这种警告..当我修复它时,应用程序无法编译 还是一样..稍后我再试一次

以上是关于如何在 Swift 4 的 NSObject 类中初始化 json 内的数组?的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中单击 NSObject 内部的 tableView 中的项目时,如何在 NSObject 类中的 UIViewController 上的 UIView 之间正确切换?

NSCoding 在 Swift 的继承类中需要初始化器

在 NSObject 类中设置协议并在 UIViewController 类中调用它们

Swift 4 - 如何在核心数据中保存 NSAttributedstring

如何在 Swift 中为 NSObject 模型变量添加值?

Swift 4.0.2 中的 NSObject setValuesForKeys 编码投诉错误