Simple and clean way to convert JSON string to Object in Swift

前端 未结 16 1056
挽巷
挽巷 2020-11-28 23:27

I have been searching for days to convert a fairly simple JSON string to an object type in Swift but with no avail.

Here is the code for web service call:



        
相关标签:
16条回答
  • 2020-11-28 23:55

    For Swift 4, i wrote this extension using the Codable protocol:

    struct Business: Codable {
        var id: Int
        var name: String
    }
    
    extension String {
    
        func parse<D>(to type: D.Type) -> D? where D: Decodable {
    
            let data: Data = self.data(using: .utf8)!
    
            let decoder = JSONDecoder()
    
            do {
                let _object = try decoder.decode(type, from: data)
                return _object
    
            } catch {
                return nil
            }
        }
    }
    
    var jsonString = "[\n" +
        "{\n" +
        "\"id\":72,\n" +
        "\"name\":\"Batata Cremosa\",\n" +
        "},\n" +
        "{\n" +
        "\"id\":183,\n" +
        "\"name\":\"Caldeirada de Peixes\",\n" +
        "},\n" +
        "{\n" +
        "\"id\":76,\n" +
        "\"name\":\"Batata com Cebola e Ervas\",\n" +
        "},\n" +
        "{\n" +
        "\"id\":56,\n" +
        "\"name\":\"Arroz de forma\",\n" +
    "}]"
    
    let businesses = jsonString.parse(to: [Business].self)
    
    0 讨论(0)
  • 2020-11-28 23:56

    As simple String extension should suffice:

    extension String {
    
        var parseJSONString: AnyObject? {
    
            let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    
            if let jsonData = data {
                // Will return an object or nil if JSON decoding fails
                return NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
            } else {
                // Lossless conversion of the string was not possible
                return nil
            }
        }
    }
    

    Then:

    var jsonString = "[\n" +
        "{\n" +
        "\"id\":72,\n" +
        "\"name\":\"Batata Cremosa\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":183,\n" +
        "\"name\":\"Caldeirada de Peixes\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":76,\n" +
        "\"name\":\"Batata com Cebola e Ervas\",\n" +            
        "},\n" +
        "{\n" +
        "\"id\":56,\n" +
        "\"name\":\"Arroz de forma\",\n" +            
    "}]"
    
    let json: AnyObject? = jsonString.parseJSONString
    println("Parsed JSON: \(json!)")
    println("json[3]: \(json![3])")
    
    /* Output:
    
    Parsed JSON: (
        {
        id = 72;
        name = "Batata Cremosa";
        },
        {
        id = 183;
        name = "Caldeirada de Peixes";
        },
        {
        id = 76;
        name = "Batata com Cebola e Ervas";
        },
        {
        id = 56;
        name = "Arroz de forma";
        }
    )
    
    json[3]: {
        id = 56;
        name = "Arroz de forma";
    }
    */
    
    0 讨论(0)
  • 2020-11-29 00:00

    I wrote a library which makes working with json data and deserialization a breeze in Swift. You can get it here: https://github.com/isair/JSONHelper

    Edit: I updated my library, you can now do it with just this:

    class Business: Deserializable {
        var id: Int?
        var name = "N/A"  // This one has a default value.
    
        required init(data: [String: AnyObject]) {
            id <-- data["id"]
            name <-- data["name"]
        }
    }
    
    var businesses: [Business]()
    
    Alamofire.request(.GET, "http://MyWebService/").responseString { (request, response, string, error) in
        businesses <-- string
    }
    

    Old Answer:

    First, instead of using .responseString, use .response to get a response object. Then change your code to:

    func getAllBusinesses() {
    
        Alamofire.request(.GET, "http://MyWebService/").response { (request, response, data, error) in
            var businesses: [Business]?
    
            businesses <-- data
    
            if businesses == nil {
                // Data was not structured as expected and deserialization failed, do something.
            } else {
                // Do something with your businesses array. 
            }
        }
    }
    

    And you need to make a Business class like this:

    class Business: Deserializable {
        var id: Int?
        var name = "N/A"  // This one has a default value.
    
        required init(data: [String: AnyObject]) {
            id <-- data["id"]
            name <-- data["name"]
        }
    }
    

    You can find the full documentation on my GitHub repo. Have fun!

    0 讨论(0)
  • 2020-11-29 00:01

    SWIFT4 - Easy and elegant way of decoding JSON strings to Struct.

    First step - encode String to Data with .utf8 encoding.

    Than decode your Data to YourDataStruct.

    struct YourDataStruct: Codable {
    
    let type, id: String
    
    init(_ json: String, using encoding: String.Encoding = .utf8) throws {
        guard let data = json.data(using: encoding) else {
            throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)
        }
        try self.init(data: data)
    }
    
    init(data: Data) throws {
        self = try JSONDecoder().decode(YourDataStruct.self, from: data)
    }                                                                      
    }
    
    do { let successResponse = try WSDeleteDialogsResponse(response) }
    } catch {}
    
    0 讨论(0)
  • 2020-11-29 00:01

    You can use swift.quicktype.io for converting JSON to either struct or class. Even you can mention version of swift to genrate code.

    Example JSON:

    {
      "message": "Hello, World!"
    }
    

    Generated code:

    import Foundation
    
    typealias Sample = OtherSample
    
    struct OtherSample: Codable {
        let message: String
    }
    
    // Serialization extensions
    
    extension OtherSample {
        static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherSample? {
            guard let data = json.data(using: encoding) else { return nil }
            return OtherSample.from(data: data)
        }
    
        static func from(data: Data) -> OtherSample? {
            let decoder = JSONDecoder()
            return try? decoder.decode(OtherSample.self, from: data)
        }
    
        var jsonData: Data? {
            let encoder = JSONEncoder()
            return try? encoder.encode(self)
        }
    
        var jsonString: String? {
            guard let data = self.jsonData else { return nil }
            return String(data: data, encoding: .utf8)
        }
    }
    
    extension OtherSample {
        enum CodingKeys: String, CodingKey {
            case message
        }
    }
    
    0 讨论(0)
  • 2020-11-29 00:06

    for swift 3/4

    extension String {
        func toJSON() -> Any? {
            guard let data = self.data(using: .utf8, allowLossyConversion: false) else { return nil }
            return try? JSONSerialization.jsonObject(with: data, options: .mutableContainers)
        }
    }
    

    Example Usage:

     let dict = myString.toJSON() as? [String:AnyObject] // can be any type here
    
    0 讨论(0)
提交回复
热议问题