【问题标题】:In Swift 3, how to convert a dictionary to Object?在 Swift 3 中,如何将字典转换为 Object?
【发布时间】:2017-09-21 01:38:52
【问题描述】:

[我是 Swift 新手,我不知道这是否可能,所以请建议我]

我有一本像这样的字典(它是动态的):

let simpleHash = ["testA": "A", "testB": "B", "testC": "C"]

我想把它转换成一个对象,这样我就可以像这样访问:

simpleHash.testA // instead of simpleHash["testA"]

我试过下面的方法,但没有帮助

let jsonData = try JSONSerialization.data(withJSONObject: simpleHash, options: .prettyPrinted)
let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])

谁能给我建议。 提前致谢!

【问题讨论】:

  • 你在说什么对象?你的字典和 JSON 有什么关系?
  • @ElTomato 我清楚地提到了我想要的字典simpleHash
  • 查看 JSONDecoder。
  • 您的意思是structclass 而不是Dictionary

标签: swift object dictionary


【解决方案1】:

Swift 需要为 testA 显式声明变量,因此您将无法 100% 保持动态。但是,由于您需要在代码中使用该变量,因此在某些时候会知道它。鉴于此,本着最小化声明约束的精神,您可以定义一个使用字典作为其内部存储并将键值作为计算属性公开的类。

这是一个例子:

class DictionaryBased
{
   var content:[String:Any]
   init(_ dictionary:[String:Any])
   { content = dictionary }

   func get<T>(_ key:String, _ defaultValue:T) -> T 
   { return content[key] as? T ?? defaultValue }

   func set<T>(_ key:String, _ value:T)  
   { content[key] = value }
}

class SimpleHash:DictionaryBased 
{}

有了这个,您可以根据需要(以及在需要的地方)使用扩展添加计算属性。

extension SimpleHash
{
  var testA:String { get { return get("testA", "") }  set { set("testA",newValue) } }
  var testB:String { get { return get("testB", "") }  set { set("testB",newValue) } }

  // if variables are "read-only", you don't need the set { } part
  var testC:String { get { return get("testC", "") }  }
}

您可以添加已键入或未键入的变量,并支持可选项,或者(如上)提供默认值。

extension SimpleHash
{
  var testD:Any?    { get { return get("testD", nil) }  set { set("testD",newValue) } }
  var testE:String? { get { return get("testE", nil) }  set { set("testE",newValue) } }
  var testF:Date?   { get { return get("testF", nil) }  set { set("testE",newValue) } }
}

要使用这个“基于字典”的对象,您需要在某个时候创建​​一个实例并为其提供字典的内容:

let simpleHash = SimpleHash(["testA": "A", "testB": "B", "testC": "C"])

simpleHash.testA  // "A"
simpleHash.testD  // nil

请注意,这不会像使用本机属性并将字典映射到每个物理变量那样高效。另一方面,它的代码要少得多。如果变量不经常被引用,额外的开销可能是为了简单性和灵活性而可以接受的折衷。

【讨论】:

    【解决方案2】:

    一个简单的struct 来保存您的Dictionary 值:

    struct SimpleStruct {
      // properties are Optional since they might not be matched
      let testA: String?
      let testB: String?
    
      // this one has a default value
      let testC: String
    
      // init that takes a Dictionary
      init(dictionary: [String:Any]) {
        // set the Optional ones
        self.testA = dictionary["testA"] as? String
        self.testB = dictionary["testB"] as? String
    
        // set the one with a default
        self.testC = dictionary["testC"] as? String ?? "C"
      }
    }
    
    let foo = SimpleStruct(dictionary: ["testA": "A", "testB": "B", "testC": "C"])
    
    // force-unwrapping for brevity
    // you should actually test before using
    print(foo.testA!) // prints A
    print(foo.testB!) // prints B
    print(foo.testC)  // prints C
    

    【讨论】:

    • 最好让初始化程序失败,而不是让所有属性都可选
    • @Alexander True,一个可失败的初始化器也可以工作。我没有让这个失败,因为我为其中一个包含了默认值。
    猜你喜欢
    • 2018-03-30
    • 1970-01-01
    • 2016-11-02
    • 2017-03-05
    • 1970-01-01
    • 2015-06-19
    • 2018-03-18
    相关资源
    最近更新 更多