将 Json 数组映射到对象失败
Mapping Json Array to Object fails
我尝试将来自服务器的 JSON 响应转换为对象。我用 Swift.
这是打印服务器响应的结果:
(
{
1 = Horst;
2 = Schnitzelhuber;
3 = "0161 2213310";
id = 0000040001;
status = 2;
},
{
1 = "Mar\U00f0a";
3 = "0163 5419374";
id = 0000040005;
status = 2;
}
)
这是我的模型:
class Profil: JSONSerializable {
var id: String?
required init() {}
class func map(source: JsonSZ, object: Profil) {
object.id <= source["id"]
}
}
到目前为止,我一直在使用 SwiftJZ 进行解析。
let test: [Profil!]? = serializer.fromJSONArray(response, to: Profil.self)
如果我尝试打印映射对象:
println(test?[0].id)
=> 结果始终为零
这是JSONSZ的相关方法:
public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject, to type: N.Type) -> [N]? {
if let string = JSON as? String {
if let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
=> FAIL if let array = parsed as? [[String: AnyObject]] {
var objects: [N] = []
for element in array {
self.values = element
var object = N()
N.map(self, object: object)
objects.append(object)
}
return objects
}
}
}
return nil
}
你能帮我快速解决这个问题吗?
也许另一个图书馆...
最后我想将模型的这个对象保存到 Cora Data 中。
编辑:
public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject, to type: N.Type) -> [N]? {
if let string = JSON as? String {
if let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
问题来了:let parsed 为 nil。这就是序列化失败的原因。
我最近一直在做类似的事情,并构建了我自己的相当基本的 JSON 解析库。
这里有一点:
JSON 类型别名
typealias JSON = AnyObject
typealias JSONObject = [String : AnyObject]
typealias JSONArray = [JSON]
JSON可解码协议
// Represents an object that can be imported via JSON
protocol JSONDecodable
{
func decodeJSON(json: JSONObject)
}
JSON 类型解析
private let iso8601DateFormatter : NSDateFormatter =
{
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormatter
}()
func jsonString(object: AnyObject?) -> String?
{
return object as? String
}
func jsonBoolean(object: AnyObject?) -> Bool?
{
return object as? Bool
}
func jsonInt(object: AnyObject?) -> Int?
{
return object as? Int
}
func jsonFloat(object: AnyObject?) -> Float?
{
return object as? Float
}
func jsonDate(object: AnyObject?) -> NSDate?
{
switch jsonString(object)
{
case .Some(let dateString): return iso8601DateFormatter.dateFromString(dateString)
case .None: return nil
}
}
func jsonDateString(date: NSDate) -> String
{
return iso8601DateFormatter.stringFromDate(date)
}
空合并赋值运算符 (a ??= b)
// Null coalesce-assignment operator (a ??= b)
infix operator ??= { associativity left precedence 90 }
func ??= <T>(inout lhs: T, rhs: T?)
{
// If the right-hand side is not-nil, assign the value to the left-hand
if let rhs = rhs { lhs = rhs }
}
JSON 结果(枚举)
// Completion handler which receives a JSON result
typealias JSONCompletionHandler = (result: JSONResult) -> Void
enum JSONResult
{
case Object(JSONObject) // Dictionary
case Array(JSONArray) // Array
case Null // No Data
case Error(NSError) // Error occurred
}
JSON 数据任务(NSURLSession 扩展)
extension NSURLSession
{
func jsonDataTaskWithRequest(request: NSURLRequest, completionHandler: JSONCompletionHandler? = nil) -> NSURLSessionDataTask
{
return self.dataTaskWithRequest(request) { data, urlResponse, error in
// Check for network error
if let error = error
{
completionHandler?(result: .Error(error))
return
}
// Check for non-200 HTTP status
if let httpResponse = urlResponse as? NSHTTPURLResponse
{
if httpResponse.statusCode < 200 || httpResponse.statusCode > 299
{
let httpError = NSError(domain: "JSONDataTask", code: httpResponse.statusCode, userInfo: nil)
completionHandler?(result: .Error(httpError))
return
}
}
var json : JSON?
// If there is data available, try to deserialize it as JSON
if data?.length > 0
{
// Deserialize the data into a JSON object
var jsonError : NSError?
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &jsonError)
if let jsonError = jsonError
{
completionHandler?(result: .Error(jsonError))
return
}
}
// Check what kind of JSON object is the root node
switch json
{
// If the root node is a JSON object
case let jsonObject as JSONObject:
completionHandler?(result: .Object(jsonObject))
// If the root node is a JSON array
case let jsonArray as JSONArray:
completionHandler?(result: .Array(jsonArray))
// If there was no JSON data
default:
completionHandler?(result: .Null)
}
}
}
}
网络代码示例
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://www.digitlabs.us")!)
let task = session.jsonDataTaskWithRequest(request) { result in
switch result
{
case Object(let object): // JSON dictionary
case Array(let array): // JSON array
case Null: // No Data
case Error(let error): // Error occurred
}
}
task.resume()
示例 NSManagedObject Class
class Message : NSManagedObject, JSONDecodable
{
@NSManaged var identifier : String
@NSManaged var subject : String
@NSManaged var bodyText : String
@NSManaged var unread : NSNumber
@NSManaged var dateSent : NSDate
var isUnread : Bool
{
get { return self.unread as Bool }
set { self.unread = NSNumber(bool: newValue) }
}
func decodeJSON(json: JSONObject)
{
self.identifier ??= jsonString(json["id"])
self.subject ??= jsonString(json["subject"])
self.bodyText ??= jsonString(json["bodyText"])
self.isUnread ??= jsonBoolean(json["isUnread"])
self.dateSent ??= jsonDate(json["dateSent"])
}
}
我尝试将来自服务器的 JSON 响应转换为对象。我用 Swift.
这是打印服务器响应的结果:
(
{
1 = Horst;
2 = Schnitzelhuber;
3 = "0161 2213310";
id = 0000040001;
status = 2;
},
{
1 = "Mar\U00f0a";
3 = "0163 5419374";
id = 0000040005;
status = 2;
}
)
这是我的模型:
class Profil: JSONSerializable {
var id: String?
required init() {}
class func map(source: JsonSZ, object: Profil) {
object.id <= source["id"]
}
}
到目前为止,我一直在使用 SwiftJZ 进行解析。
let test: [Profil!]? = serializer.fromJSONArray(response, to: Profil.self)
如果我尝试打印映射对象:
println(test?[0].id)
=> 结果始终为零
这是JSONSZ的相关方法:
public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject, to type: N.Type) -> [N]? {
if let string = JSON as? String {
if let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
=> FAIL if let array = parsed as? [[String: AnyObject]] {
var objects: [N] = []
for element in array {
self.values = element
var object = N()
N.map(self, object: object)
objects.append(object)
}
return objects
}
}
}
return nil
}
你能帮我快速解决这个问题吗?
也许另一个图书馆...
最后我想将模型的这个对象保存到 Cora Data 中。
编辑:
public func fromJSONArray<N: JSONSerializable>(JSON: AnyObject, to type: N.Type) -> [N]? {
if let string = JSON as? String {
if let data = JSON.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) {
let parsed: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil)
问题来了:let parsed 为 nil。这就是序列化失败的原因。
我最近一直在做类似的事情,并构建了我自己的相当基本的 JSON 解析库。
这里有一点:
JSON 类型别名
typealias JSON = AnyObject
typealias JSONObject = [String : AnyObject]
typealias JSONArray = [JSON]
JSON可解码协议
// Represents an object that can be imported via JSON
protocol JSONDecodable
{
func decodeJSON(json: JSONObject)
}
JSON 类型解析
private let iso8601DateFormatter : NSDateFormatter =
{
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormatter
}()
func jsonString(object: AnyObject?) -> String?
{
return object as? String
}
func jsonBoolean(object: AnyObject?) -> Bool?
{
return object as? Bool
}
func jsonInt(object: AnyObject?) -> Int?
{
return object as? Int
}
func jsonFloat(object: AnyObject?) -> Float?
{
return object as? Float
}
func jsonDate(object: AnyObject?) -> NSDate?
{
switch jsonString(object)
{
case .Some(let dateString): return iso8601DateFormatter.dateFromString(dateString)
case .None: return nil
}
}
func jsonDateString(date: NSDate) -> String
{
return iso8601DateFormatter.stringFromDate(date)
}
空合并赋值运算符 (a ??= b)
// Null coalesce-assignment operator (a ??= b)
infix operator ??= { associativity left precedence 90 }
func ??= <T>(inout lhs: T, rhs: T?)
{
// If the right-hand side is not-nil, assign the value to the left-hand
if let rhs = rhs { lhs = rhs }
}
JSON 结果(枚举)
// Completion handler which receives a JSON result
typealias JSONCompletionHandler = (result: JSONResult) -> Void
enum JSONResult
{
case Object(JSONObject) // Dictionary
case Array(JSONArray) // Array
case Null // No Data
case Error(NSError) // Error occurred
}
JSON 数据任务(NSURLSession 扩展)
extension NSURLSession
{
func jsonDataTaskWithRequest(request: NSURLRequest, completionHandler: JSONCompletionHandler? = nil) -> NSURLSessionDataTask
{
return self.dataTaskWithRequest(request) { data, urlResponse, error in
// Check for network error
if let error = error
{
completionHandler?(result: .Error(error))
return
}
// Check for non-200 HTTP status
if let httpResponse = urlResponse as? NSHTTPURLResponse
{
if httpResponse.statusCode < 200 || httpResponse.statusCode > 299
{
let httpError = NSError(domain: "JSONDataTask", code: httpResponse.statusCode, userInfo: nil)
completionHandler?(result: .Error(httpError))
return
}
}
var json : JSON?
// If there is data available, try to deserialize it as JSON
if data?.length > 0
{
// Deserialize the data into a JSON object
var jsonError : NSError?
json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &jsonError)
if let jsonError = jsonError
{
completionHandler?(result: .Error(jsonError))
return
}
}
// Check what kind of JSON object is the root node
switch json
{
// If the root node is a JSON object
case let jsonObject as JSONObject:
completionHandler?(result: .Object(jsonObject))
// If the root node is a JSON array
case let jsonArray as JSONArray:
completionHandler?(result: .Array(jsonArray))
// If there was no JSON data
default:
completionHandler?(result: .Null)
}
}
}
}
网络代码示例
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://www.digitlabs.us")!)
let task = session.jsonDataTaskWithRequest(request) { result in
switch result
{
case Object(let object): // JSON dictionary
case Array(let array): // JSON array
case Null: // No Data
case Error(let error): // Error occurred
}
}
task.resume()
示例 NSManagedObject Class
class Message : NSManagedObject, JSONDecodable
{
@NSManaged var identifier : String
@NSManaged var subject : String
@NSManaged var bodyText : String
@NSManaged var unread : NSNumber
@NSManaged var dateSent : NSDate
var isUnread : Bool
{
get { return self.unread as Bool }
set { self.unread = NSNumber(bool: newValue) }
}
func decodeJSON(json: JSONObject)
{
self.identifier ??= jsonString(json["id"])
self.subject ??= jsonString(json["subject"])
self.bodyText ??= jsonString(json["bodyText"])
self.isUnread ??= jsonBoolean(json["isUnread"])
self.dateSent ??= jsonDate(json["dateSent"])
}
}