Ios 如何在Swift 2中正确地从JSON实例化数据模型

Ios 如何在Swift 2中正确地从JSON实例化数据模型,ios,swift,struct,swift2,models,Ios,Swift,Struct,Swift2,Models,我正在寻找一种干净、正确的方法来在swift中实例化数据模型 我已经搜索了一段时间,但还没有找到确切的答案。我发现了很多用于教学目的的简单例子(比如苹果公司自己提出的例子),但不是真实的案例。我的意思是:如何从API返回的复杂JSON实例化一个数据模型,同时优雅地管理选项和可失败的初始化 我对纯swift风格感兴趣,所以请不要使用obj-c解决方案或建议库来轻松处理swift中的JSON,因为这不是我问题的真正重点。任何东西都有第三方库(我也使用它们),但我在这里寻找的是深入了解swift语法并

我正在寻找一种干净、正确的方法来在swift中实例化数据模型

我已经搜索了一段时间,但还没有找到确切的答案。我发现了很多用于教学目的的简单例子(比如苹果公司自己提出的例子),但不是真实的案例。我的意思是:如何从API返回的复杂JSON实例化一个数据模型,同时优雅地管理选项和可失败的初始化

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

下面,我提出了我迄今为止采用的几种解决方案。对你的建议、论点和解释很感兴趣

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

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

2) 哪种分配模式最有效<代码>如果让绑定或保护绑定

3) 如何正确处理作为“我的实际模型”属性的模型的实例化?(考虑以下截图中的
var myObjects

对于上面的每一个问题,我都已经找到了答案,但我对其他观点感兴趣,因为我认为Swift是一种非常丰富和灵活的语言,苹果的官方文档有时缺乏关于最佳实践的清晰性

//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
        }
      }
    } 
}

我认为没有任何“优雅”的方式来处理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)
}

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

我认为没有任何“优雅”的方式来处理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)
}

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

方案1是最好的,因为它有guard语句和failable初始值设定项。那么,您还期望什么呢?使用Swift JSON库的反对理由是什么?它使代码更具可读性和可读性concise@Darko我编辑。对于Kametrixom:我并不反对JSON库(我每天都使用它们)。在这里,我强调纯粹的Swift风格,因为我想了解Swift直到最后,以提高我的技能。我希望这个问题得到更多的关注。这正是我现在从Objective-C转到SwiftProposition 1时问自己的问题,因为guard声明和失败的初始值设定项。那么,您还期望什么呢?使用Swift JSON库的反对理由是什么?它使代码更具可读性和可读性concise@Darko我编辑。对于Kametrixom:我并不反对JSON库(我每天都使用它们)。在这里,我强调纯粹的Swift风格,因为我想了解Swift直到最后,以提高我的技能。我希望这个问题得到更多的关注。这正是我从Objective-C转到Swift时问自己的问题