Parse json in Swift, AnyObject type

后端 未结 3 2023
北荒
北荒 2020-12-05 02:02

I\'m trying to parse a json but I have some difficulties with the data types and notably the AnyObject type + downcasting.

Let\'s consider the following json (it\'s

相关标签:
3条回答
  • 2020-12-05 02:39

    Try:

    • 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-12-05 02:45

    This works fine for me in the playground and in the terminal using env xcrun swift

    UPDATED FOR SWIFT 4 AND CODABLE

    Here is a Swift 4 example using the Codable protocol.

    var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
    
    struct Weather: Codable {
        let id: Int
        let main: String
        let description: String
        let icon: String
    }
    
    struct Result: Codable {
        let weather: [Weather]
    }
    
    do {
        let weather = try JSONDecoder().decode(Result.self, from: jsonStr.data(using: .utf8)!)
        print(weather)
    }
    catch {
        print(error)
    }
    

    UPDATED FOR SWIFT 3.0

    I have updated the code for Swift 3 and also showed how to wrap the parsed JSON into objects. Thanks for all the up votes!

    import Foundation
    
    struct Weather {
        let id: Int
        let main: String
        let description: String
        let icon: String
    }
    
    extension Weather {
        init?(json: [String: Any]) {
            guard
                let id = json["id"] as? Int,
                let main = json["main"] as? String,
                let description = json["description"] as? String,
                let icon = json["icon"] as? String
            else { return nil }
            self.id = id
            self.main = main
            self.description = description
            self.icon = icon
        }
    }
    
    var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
    
    enum JSONParseError: Error {
        case notADictionary
        case missingWeatherObjects
    }
    
    var data = jsonStr.data(using: String.Encoding.ascii, allowLossyConversion: false)
    do {
        var json = try JSONSerialization.jsonObject(with: data!, options: [])
        guard let dict = json as? [String: Any] else { throw JSONParseError.notADictionary }
        guard let weatherJSON = dict["weather"] as? [[String: Any]] else { throw JSONParseError.missingWeatherObjects }
        let weather = weatherJSON.flatMap(Weather.init)
        print(weather)
    }
    catch {
        print(error)
    }
    

    -- Previous Answer --

    import Foundation
    
    var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
    var data = jsonStr.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
    var localError: NSError?
    var json: AnyObject! = NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: &localError)
    
    if let dict = json as? [String: AnyObject] {
        if let weather = dict["weather"] as? [AnyObject] {
            for dict2 in weather {
                let id = dict2["id"]
                let main = dict2["main"]
                let description = dict2["description"]
                println(id)
                println(main)
                println(description)
            }
        }
    }
    

    Since I'm still getting up-votes for this answer, I figured I would revisit it for Swift 2.0:

    import Foundation
    
    var jsonStr = "{\"weather\":[{\"id\":804,\"main\":\"Clouds\",\"description\":\"overcast clouds\",\"icon\":\"04d\"}],}"
    var data = jsonStr.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
    do {
        var json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
    
        if let dict = json as? [String: AnyObject] {
            if let weather = dict["weather"] as? [AnyObject] {
                for dict2 in weather {
                    let id = dict2["id"] as? Int
                    let main = dict2["main"] as? String
                    let description = dict2["description"] as? String
                    print(id)
                    print(main)
                    print(description)
                }
            }
        }
    
    }
    catch {
        print(error)
    }
    

    The biggest difference is that the variable json is no longer an optional type and the do/try/catch syntax. I also went ahead and typed id, main, and description.

    0 讨论(0)
  • 2020-12-05 02:51

    Using my library (https://github.com/isair/JSONHelper) you can do this with your json variable of type AnyObject:

    var weathers = [Weather]() // If deserialization fails, JSONHelper just keeps the old value in a non-optional variable. This lets you assign default values like this.
    
    if let jsonDictionary = json as? JSONDictionary { // JSONDictionary is an alias for [String: AnyObject]
      weathers <-- jsonDictionary["weather"]
    }
    

    Had your array not been under the key "weather", your code would have been just this:

    var weathers = [Weather]()
    weathers <-- json
    

    Or if you have a json string in your hands you can just pass it as well, instead of creating a JSON dictionary from the string first. The only setup you need to do is writing a Weather class or struct:

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