Deserialize JSON / NSDictionary to Swift objects

前端 未结 13 1503
情歌与酒
情歌与酒 2020-11-29 18:43

Is there a way to properly deserialize a JSON response to Swift objects resp. using DTOs as containers for fixed JSON APIs?

Something similar to http://james.newtonk

相关标签:
13条回答
  • 2020-11-29 18:59

    SWIFT 4 Update


    Since you give a very simple JSON object the code prepared for to handle that model. If you need more complicated JSON models you need to improve this sample.

    Your Custom Object

    class Person : NSObject {
        var name : String = ""
        var email : String = ""
        var password : String = ""
    
        init(JSONString: String) {
            super.init()
    
            var error : NSError?
            let JSONData = JSONString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    
            let JSONDictionary: Dictionary = NSJSONSerialization.JSONObjectWithData(JSONData, options: nil, error: &error) as NSDictionary
    
            // Loop
            for (key, value) in JSONDictionary {
                let keyName = key as String
                let keyValue: String = value as String
    
                // If property exists
                if (self.respondsToSelector(NSSelectorFromString(keyName))) {
                    self.setValue(keyValue, forKey: keyName)
                }
            }
            // Or you can do it with using 
            // self.setValuesForKeysWithDictionary(JSONDictionary)
            // instead of loop method above
        }
    }
    

    And this is how you invoke your custom class with JSON string.

    override func viewDidLoad() {
        super.viewDidLoad()
        let jsonString = "{ \"name\":\"myUser\", \"email\":\"user@example.com\", \"password\":\"passwordHash\" }"
        var aPerson : Person = Person(JSONString: jsonString)
        println(aPerson.name) // Output is "myUser"
    }
    
    0 讨论(0)
  • 2020-11-29 18:59

    I recommend that you use code generation (http://www.json4swift.com) to create native models out of the json response, this will save your time of parsing by hand and reduce the risk of errors due to mistaken keys, all elements will be accessible by model properties, this will be purely native and the models will make more sense rather checking the keys.

    Your conversion will be as simple as:

    let userObject = UserClass(userDictionary)
    print(userObject!.name)
    
    0 讨论(0)
  • 2020-11-29 19:04

    There's a great example by Apple for deserializing JSON with Swift 2.0

    The trick is to use the guard keyword and chain the assignments like so:

    init?(attributes: [String : AnyObject]) {
        guard let name = attributes["name"] as? String,
            let coordinates = attributes["coordinates"] as? [String: Double],
            let latitude = coordinates["lat"],
            let longitude = coordinates["lng"],
            else {
                return nil
        }
        self.name = name
        self.coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }
    

    I personally prefer native parsing vs any 3rd party, as it is transparent and magic-less. (and bug less?)

    0 讨论(0)
  • 2020-11-29 19:07

    If you would like parse from and to json without the need to manually map keys and fields, then you could also use EVReflection. You can then use code like:

    var user:User = User(json:jsonString)
    

    or

    var jsonString:String = user.toJsonString()
    

    The only thing you need to do is to use EVObject as your data objects base class. See the GitHub page for more detailed sample code

    0 讨论(0)
  • 2020-11-29 19:08

    Yet another JSON handler I wrote:

    • https://github.com/dankogai/swift-json

    With it you can go like this:

    let obj:[String:AnyObject] = [
        "array": [JSON.null, false, 0, "", [], [:]],
        "object":[
            "null":   JSON.null,
            "bool":   true,
            "int":    42,
            "double": 3.141592653589793,
            "string": "a α\t弾\n                                                                    
    0 讨论(0)
  • 2020-11-29 19:09

    I wrote this small open-source library recently that lets you quickly and easily deserialize dictionaries into Swift objects: https://github.com/isair/JSONHelper

    Using it, deserializing data becomes as easy as this:

    var myInstance = MyClass(data: jsonDictionary)
    

    or

    myInstance <-- jsonDictionary
    

    And models need to look only like this:

    struct SomeObjectType: Deserializable {
        var someProperty: Int?
        var someOtherProperty: AnotherObjectType?
        var yetAnotherProperty: [YetAnotherObjectType]?
    
        init(data: [String: AnyObject]) {
            someProperty <-- data["some_key"]
            someOtherProperty <-- data["some_other_key"]
            yetAnotherProperty <-- data["yet_another_key"]
        }
    }
    

    Which, in your case, would be:

    struct Person: Deserializable {
        var name: String?
        var email: String?
        var password: String?
    
        init(data: [String: AnyObject]) {
            name <-- data["name"]
            email <-- data["email"]
            password <-- data["password"]
        }
    }
    
    0 讨论(0)
提交回复
热议问题