【问题标题】:How to correctly instantiating data model from JSON in Swift 2如何在 Swift 2 中正确地从 JSON 实例化数据模型
【发布时间】:2015-11-10 17:42:51
【问题描述】:

我正在寻找一种干净且正确的方法来快速实例化数据模型。

我一直在寻找一段时间,但我还没有找到明确的答案。我发现了很多用于教学目的的简单示例(例如 Apple 自己提出的here),但不是真实案例。我的意思是:如何从 API 返回的复杂 JSON 实例化数据模型,同时优雅地管理可选项和失败的初始化?

我对纯 swift 风格感兴趣,所以请不要使用 obj-c 解决方案或建议库来轻松处理 JSONS,因为这不是我问题的真正重点。所有东西都有第三方库(我也使用它们),但我在这里寻找的是深入学习 swift 语法并了解其内部模式。

下面我提出了几个我迄今为止采用的解决方案。对您的建议、论点和解释非常感兴趣。

编辑: 我特别关心的一些方面:

1) 假设模型的属性可以设置为nil,那么哪个是最好的属性声明?作为可选?作为未包装的可选?

2) 哪种分配模式效果最好? if let 绑定还是guard 绑定?

3) 如何正确处理作为我的实际模型属性的模型的实例化? (在下面的片段中考虑var myObjects

对于上面的每个问题,我已经找到了答案,但我对其他观点感兴趣,因为我认为 Swift 是一种非常丰富且具有延展性的语言,而 Apple 官方文档有时对最佳实践缺乏明确性。

//Proposition 2: property as Optionals and use of guard let

struct MyModel {

    let a: String?
    let b: MyOtherModel? // MyOtherModel is another struct similar to this one
    var myObjects = [Object]()  // Object is another struct similar to this one

    init?(data: AnyObject) {

      guard let data = data as? JSON,
            let a = json["a"] as? String,
            let otherData = json["b"] as AnyObject,
            let myObjectsArray = json["objects"] as? [AnyObject] else {
        return nil
      }
      self.a = a
      self.b = MyOtherModel(otherData)

      for data in myObjectsArray {
        if let newObject = Object(data) {
          self.myObjects.append(newObject)
        }
      }
    } 

}


//Proposition 2: properties as unwrapped Optionals and if let bindings

struct MyModel {

    let a: String!
    let b: MyOtherModel! // MyOtherModel is another struct similar to this one
    var myObjects = [Object]()  // Object is another struct similar to this one

    init?(data: AnyObject) {

      if let data = data as? JSON,
         let a = json["a"] as? String,
         let otherData = json["b"] as AnyObject,
         let myObjectsArray = json["objects"] as? [AnyObject] {

        self.a = a
        self.b = MyOtherModel(otherData)
        for data in myObjectsArray {
          if let newObject = Object(data) {
            self.myObjects.append(newObject)
          }
        }
      }
      else {
        return nil
      }
    } 

}

//Proposition 3: properties already initialized, forcing unwrapping of json sub-objects

struct MyModel {

    let a = String()
    let b = MyOtherModel() // MyOtherModel is another struct similar to this one
    var myObjects = [Object]()  // Object is another struct similar to this one

    init?(data: AnyObject) {

        self.a = data["a"]
        self.b = MyOtherModel(data["b"]!!)

        if let myObjectsArray = data["b"] as [AnyObject] {
          for data in myObjectsArray {
            if let newObject = Object(data) {
              self.myObjects.append(newObject)
            }
          }
        }
        if (self.a.isEmpty) {
          return nil
        }
      }
    } 
}

【问题讨论】:

  • 命题 1 是最好的,因为有保护语句和可失败的初始化程序。那么,您还有什么期待呢?
  • 什么是反对使用 Swift JSON 库?它使代码更具可读性和简洁性
  • @Darko 我编辑了。对于 Kametrixom:我不反对 JSON 库(我每天都使用它们)。在这里我强调纯 Swift 风格,因为我想了解 Swift 到底以提高我的技能。
  • 我希望这个问题得到更多关注。这是我现在从 Objective-C 迁移到 Swift 时问自己的确切问题

标签: ios swift struct swift2 models


【解决方案1】:

我认为没有任何“优雅”的方式来处理 JSON。就可读代码而言,我通常采用这种方法,并不是说这是唯一的方法:

型号:

class Category : NSObject {

    // Model Objects
    var categoryId: NSNumber!
    var categoryDesc: String!
    var inAppId: String!
    var categoryUnlocked: NSNumber!

    override init() {
        self.categoryId         = 0
        self.categoryDesc       = ""
        self.inAppId            = ""
        self.categoryUnlocked   = 0
    }

    convenience init(categoryDictionary: [String : AnyObject]) {
        self.init()

        self.categoryId         = NSNumber(int: categoryDictionary["CategoryID"]!.intValue)
        self.categoryDesc       = categoryDictionary["Category_Desc"] as? String ?? ""
        self.inAppId            = categoryDictionary["InAppID"] as? String ?? ""
        self.categoryUnlocked   = categoryDictionary["CategoryUnlocked"] as? NSNumber ?? 0
    }

}

对于 JSON,我使用 array.map 函数:

var categoryList = [Category]()
if let catArray = data["categories"] as? NSArray {
      categoryList = catArray.map({Category(categoryDictionary: $0 as! [String : AnyObject])})
      CoreDataService.instance.saveCategories(categoryList)
}

这种方式对于未来的开发人员来说是整洁易读的,并且在特定模型中易于管理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 2021-10-08
    相关资源
    最近更新 更多