将JSON / NSDictionary反序列化为Swift对象
有没有一种方法正确反序列化的Swift对象响应的JSON响应。 使用DTO作为固定JSON API的容器?
类似于http://james.newtonking.com/json或类似于Java的这个例子
User user = jsonResponse.readEntity(User.class);
由此jsonResponse.toString()
是类似的
{ "name": "myUser", "email": "user@example.com", "password": "passwordHash" }
SWIFT 4更新
既然你给了一个非常简单的JSON对象,准备处理这个模型的代码。 如果您需要更复杂的JSON模型,则需要改进此示例。
您的自定义对象
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 } }
这就是你如何用JSONstring调用你的自定义类。
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" }
Swift 2 :我真的很喜欢Mohacs以前的post! 为了使它更加面向对象,我写了一个匹配的扩展:
extension NSObject{ convenience init(jsonStr:String) { self.init() if let jsonData = jsonStr.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) { do { let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String: AnyObject] // Loop for (key, value) in json { let keyName = key as String let keyValue: String = value as! String // If property exists if (self.respondsToSelector(NSSelectorFromString(keyName))) { self.setValue(keyValue, forKey: keyName) } } } catch let error as NSError { print("Failed to load: \(error.localizedDescription)") } } else { print("json is of wrong format!") } } }
自定义类:
class Person : NSObject { var name : String? var email : String? var password : String? } class Address : NSObject { var city : String? var zip : String? }
使用JSONstring调用自定义类:
var jsonString = "{ \"name\":\"myUser\", \"email\":\"user@example.com\", \"password\":\"passwordHash\" }" let aPerson = Person(jsonStr: jsonString) print(aPerson.name!) // Output is "myUser" jsonString = "{ \"city\":\"Berlin\", \"zip\":\"12345\" }" let aAddress = Address(jsonStr: jsonString) print(aAddress.city!) // Output is "Berlin"
我build议你使用代码生成( http://www.json4swift.com )从json响应中创build原生模型,这样可以节省你手工分析的时间,并减less由于错误的键而导致错误的风险,所有元素将被模型属性访问,这将是纯粹的本地和模型将更有意义,而不是检查的关键。
您的转换将如下简单:
let userObject = UserClass(userDictionary) print(userObject!.name)
还有另一个我写的JSON处理程序:
有了它,你可以这样走:
let obj:[String:AnyObject] = [ "array": [JSON.null, false, 0, "", [], [:]], "object":[ "null": JSON.null, "bool": true, "int": 42, "double": 3.141592653589793, "string": "a α\t弾\n𪚲", "array": [], "object": [:] ], "url":"http://blog.livedoor.com/dankogai/" ] let json = JSON(obj) json.toString() json["object"]["null"].asNull // NSNull() json["object"]["bool"].asBool // true json["object"]["int"].asInt // 42 json["object"]["double"].asDouble // 3.141592653589793 json["object"]["string"].asString // "a α\t弾\n𪚲" json["array"][0].asNull // NSNull() json["array"][1].asBool // false json["array"][2].asInt // 0 json["array"][3].asString // ""
你看不到!?
下标之间需要。
除此之外,您可以像这样应用自己的模式:
//// schema by subclassing class MyJSON : JSON { override init(_ obj:AnyObject){ super.init(obj) } override init(_ json:JSON) { super.init(json) } var null :NSNull? { return self["null"].asNull } var bool :Bool? { return self["bool"].asBool } var int :Int? { return self["int"].asInt } var double:Double? { return self["double"].asDouble } var string:String? { return self["string"].asString } var url: String? { return self["url"].asString } var array :MyJSON { return MyJSON(self["array"]) } var object:MyJSON { return MyJSON(self["object"]) } } let myjson = MyJSON(obj) myjson.object.null // NSNull? myjson.object.bool // Bool? myjson.object.int // Int? myjson.object.double // Double? myjson.object.string // String? myjson.url // String?
我最近编写了这个小型的开源库,可以让你快速轻松地将字典反序列化为Swift对象: https : //github.com/isair/JSONHelper
使用它,反序列化数据变得如此简单:
var myInstance = MyClass(data: jsonDictionary)
要么
myInstance <-- jsonDictionary
模型只需要看起来像这样:
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"] } }
在你的情况下,这将是:
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"] } }
如果你想从jsonparsing而不需要手动映射键和字段,那么你也可以使用EVReflection 。 然后你可以使用如下代码:
var user:User = User(json:jsonString)
要么
var jsonString:String = user.toJsonString()
你唯一需要做的就是使用EVObject作为数据对象的基类。 有关更详细的示例代码,请参阅GitHub页面
苹果用Swift 2.0反序列化JSON是一个很好的例子
诀窍是使用guard关键字并链接分配,如下所示:
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) }
我个人比任何第三方都更喜欢本地parsing,因为它是透明和无魔力的。 (和bug更less?)
HandyJSON
是为您处理JSON的另一种select。 https://github.com/alibaba/handyjson
它释放JSON直接反对。 不需要指定映射关系,不需要从NSObjectinheritance。 只需定义你的纯粹的快速类/结构,并对其进行反序列化JSON即可。
类动物:HandyJSON { var name:String? var id:String? var num:Int? 需要init(){} } 让jsonString =“{\”name \“:\”cat \“,\”id \“:\”12345 \“,\”num \“:180} 如果让动物= JSONDeserializer.deserializeFrom(jsonString){ 打印(动物) }
我正在扩展Mohacs和Peter Kreinz的优秀答案,以便涵盖类似对象的情况,其中每个对象都包含有效的JSON数据types的混合。 如果parsing的JSON数据是包含JSON数据types混合的类似对象的数组,则parsingJSON数据的do循环变成这样。
// Array of parsed objects var parsedObjects = [ParsedObject]() do { let json = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as [Dictionary<String, AnyObject>] // Loop through objects for dict in json { // ParsedObject is a single instance of an object inside the JSON data // Its properties are a mixture of String, Int, Double and Bool let parsedObject = ParsedObject() // Loop through key/values in object parsed from JSON for (key, value) in json { // If property exists, set the value if (parsedObject.respondsToSelector(NSSelectorFromString(keyName))) { // setValue can handle AnyObject when assigning property value parsedObject.setValue(keyValue, forKey: keyName) } } parsedObjects.append(parsedObject) } } catch let error as NSError { print("Failed to load: \(error.localizedDescription)") }
这种方式可以让你从一个URL获取用户。 它将NSDataparsing为NSDictionary,然后parsingNSObject。
let urlS = "http://api.localhost:3000/" func getUser(username: Strung) -> User { var user = User() let url = NSURL(string: "\(urlS)\(username)") if let data = NSData(contentsOfURL: url!) { setKeysAndValues(user, dictionary: parseData(data)) } return user } func setKeysAndValues (object : AnyObject, dictionary : NSDictionary) -> AnyObject { for (key, value) in dictionary { if let key = key as? String, let value = value as? String { if (object.respondsToSelector(NSSelectorFromString(key))) { object.setValue(value, forKey: key) } } } return object } func parseData (data : NSData) -> NSDictionary { var error: NSError? return NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSDictionary }
使用quicktype ,我从你的示例生成了你的模型和序列化助手:
import Foundation struct User: Codable { let name: String let email: String let password: String } extension User { static func from(json: String, using encoding: String.Encoding = .utf8) -> OtherUser? { guard let data = json.data(using: encoding) else { return nil } return OtherUser.from(data: data) } static func from(data: Data) -> OtherUser? { let decoder = JSONDecoder() return try? decoder.decode(OtherUser.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) } }
然后parsingUser
值如下:
let user = User.from(json: """{ "name": "myUser", "email": "user@example.com", "password": "passwordHash" }""")!
你通过使用NSJSONSerialization来做到这一点 。 数据是你的JSON。
首先将它封装在if语句中以提供一些error handlingfunction
if let data = data, json = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String: AnyObject] { // Do stuff } else { // Do stuff print("No Data :/") }
然后分配他们:
let email = json["email"] as? String let name = json["name"] as? String let password = json["password"] as? String
现在,这会告诉你结果:
print("Found User iname: \(name) with email: \(email) and pass \(password)")
采取从这个SwiftparsingJSON教程。 你应该看看教程,因为它深入了很多,涵盖了更好的error handling。
- AngularJS – 服务器端validation和客户端表单
- 如何在Javascript / HTML5中parsingExcel文件
- 如何在Objective-C for iPhone中将Google Directions API多段线字段解码为纬度长点?
- JSON到stringvariables转储
- pinterest API文档
- 在Swift 3中正确parsingJSON
- Spring MVC – HttpMediaTypeNotAcceptableException
- 如何使用JSON.NET反序列化为嵌套/recursionDictionary和List?
- <Django对象>不是JSON可序列化的