2015-08-12 18 views
21

Tôi khá mới đối với lập trình iOS. Tuy nhiên, tôi đã giả định rằng Swift sẽ có một cách tự động chuyển đổi các đối tượng thành JSON và ngược lại. Điều đó đang được nói, tôi đã tìm thấy một số thư viện có thể làm điều này.Cách chuyển đổi đối tượng Swift thành từ điển

TUY NHIÊN ...

Dường như không có vấn đề làm thế nào bạn gửi dữ liệu đến một dịch vụ web (thậm chí sử dụng một cái gì đó giống như AlamoFire), yêu cầu phải có một cuốn từ điển. Tất cả các diễn đàn này cho thấy các ví dụ về việc chuyển đổi chuỗi JSON trả về thành các đối tượng dễ dàng như thế nào. Thật. Nhưng yêu cầu cần phải được mã hóa theo cách thủ công. Đó là, đi qua tất cả các thuộc tính đối tượng và ánh xạ chúng như một từ điển.

Vì vậy, câu hỏi của tôi là: Tôi có thiếu gì đó không? Tôi đã có tất cả điều này sai và có một cách siêu dễ dàng để hoặc (a) gửi JSON (thay vì một từ điển) trong YÊU CẦU hoặc (b) chuyển đổi một đối tượng tự động vào một từ điển?

Một lần nữa, tôi thấy việc xử lý phản hồi JSON dễ dàng như thế nào. Tôi chỉ đang tìm kiếm một cách tự động để chuyển đổi đối tượng yêu cầu mà tôi muốn đăng lên dịch vụ web thành định dạng mà một thư viện như AlamoFire (hoặc bất kỳ thứ gì) yêu cầu. Với các ngôn ngữ khác, điều này khá tầm thường, vì vậy tôi hy vọng có một cách dễ dàng và tự động như nhau với Swift.

Trả lời

4

Swift hiện không hỗ trợ phản chiếu nâng cao như Java hoặc C# để câu trả lời là: không, không có cách nào cũng dễ dàng và tự động với Swift thuần túy.

[Cập nhật] Swift 4 trong khi đó giao thức Codable cho phép tuần tự hóa/từ JSON và PLIST.

typealias Codable = Decodable & Encodable 
+0

thực sự phản ánh không phải là nâng cao như các ngôn ngữ khác nhưng bạn vẫn có một số cách để đạt được điều này, xem [câu trả lời của tôi] (http://stackoverflow.com/questions/31971256/how-to-convert-a-swift- object-to-a-dictionary/32682463 # 32682463) – fencingCode

+1

Tôi đã viết câu trả lời trong lần Swift 1.2. – Darko

40

Tôi không đồng ý với @Darko.

Trong Swift 2,

sử dụng giao thức lập trình hướng và sự phản ánh đơn giản được cung cấp bởi Gương lớp:

protocol JSONAble {} 

extension JSONAble { 
    func toDict() -> [String:Any] { 
     var dict = [String:Any]() 
     let otherSelf = Mirror(reflecting: self) 
     for child in otherSelf.children { 
      if let key = child.label { 
       dict[key] = child.value 
      } 
     } 
     return dict 
    } 
} 

sau đó bạn có thể sử dụng giao thức này với lớp yêu cầu của bạn và tạo ra từ điển mong muốn:

class JsonRequest : JSONAble { 
    var param1 : String? 
    // ... 
} 

let request = JsonRequest() 
// set params of the request 
let dict = request.toDict() 
// use your dict 
+1

child.value thuộc loại Bất kỳ, bạn mất thông tin loại.Vì vậy, làm thế nào để phản ánh một cây đối tượng sâu với các đối tượng khác, mảng, từ điển, vv? – Darko

+2

làm thế nào là nó không có giấy tờ? xem [Apple API] (https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_Mirror_Structure/index.html#//apple_ref/swift/tdef/s:VSs6Mirror5Child) vui lòng – fencingCode

+2

Apple Swift Tham chiếu thư viện chuẩn: ['Tham chiếu cấu trúc gương'] (https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Mirror_Structure/index.html) ... đây là liên kết phát hành thay vì đã nhận xét trước đó ".../prerelease/ios /…" liên kết. –

2

Bạn cũng có thể sử dụng thư viện ObjectMapper. Nó có một phương thức "toJSON" để chuyển đổi đối tượng của bạn thành một từ điển.

3

Nếu không sử dụng phản chiếu, và các công trình cho các đối tượng lồng nhau (Swift 4):

protocol Serializable { 
    var properties:Array<String> { get } 
    func valueForKey(key: String) -> Any? 
    func toDictionary() -> [String:Any] 
} 

extension Serializable { 
    func toDictionary() -> [String:Any] { 
     var dict:[String:Any] = [:] 

     for prop in self.properties { 
      if let val = self.valueForKey(key: prop) as? String { 
       dict[prop] = val 
      } else if let val = self.valueForKey(key: prop) as? Int { 
       dict[prop] = val 
      } else if let val = self.valueForKey(key: prop) as? Double { 
       dict[prop] = val 
      } else if let val = self.valueForKey(key: prop) as? Array<String> { 
       dict[prop] = val 
      } else if let val = self.valueForKey(key: prop) as? Serializable { 
       dict[prop] = val.toDictionary() 
      } else if let val = self.valueForKey(key: prop) as? Array<Serializable> { 
       var arr = Array<[String:Any]>() 

       for item in (val as Array<Serializable>) { 
        arr.append(item.toDictionary()) 
       } 

       dict[prop] = arr 
      } 
     } 

     return dict 
    } 
} 

Chỉ cần thực hiện tính và valueForKey cho tùy chỉnh các đối tượng bạn muốn chuyển đổi. Ví dụ:

class Question { 
    let title:String 
    let answer:Int 

    init(title:String, answer:Int) { 
     self.title = title 
     self.answer = answer 
    } 
} 
extension Question : Serializable { 
    var properties: Array<String> { 
     return ["title", "answer"] 
    } 

    func valueForKey(key: String) -> Any? { 
     switch key { 
     case "title": 
      return title 
     case "answer": 
      return answer 
     default: 
      return nil 
     } 
    } 
} 

Bạn có thể thêm các loại giá trị khác trong hàm toDictionary nếu cần.

+0

Câu trả lời này có nhanh hơn nhiều lần so với sử dụng Mirror không? Làm việc cho tôi – pwcremin

Các vấn đề liên quan