[英]Swift parse JSON to Model Object
我在這里有此方法,它完全按需返回了我的數據:
func getTestData() -> [Any]?
{
return [GradingData(lot: "lot", andColumns: "andColumns", SLAIssuedFinalGrading: true, SLAIssuedFinalGradingDate: "SLAIssuedFinalGradingDate", CityApprovalIssued: true, CityCommentReceived: false, GradingRepair: "GradingRepair", CurbStopRepair: "CurbStopRepair", SplashPadDownSpout: "SplashPadDownSpout", RYCBOtherRepairs: "RYCBOtherRepairs", Comments: "Comments", columnCamera: "", DepositReceived: false), GradingData(lot: "lot", andColumns: "andColumns2", SLAIssuedFinalGrading: false, SLAIssuedFinalGradingDate: "SLAIssuedFinalGradingDate", CityApprovalIssued: false, CityCommentReceived: false, GradingRepair: "GradingRepair", CurbStopRepair: "CurbStopRepair", SplashPadDownSpout: "SplashPadDownSpout", RYCBOtherRepairs: "RYCBOtherRepairs", Comments: "Comments", columnCamera: "", DepositReceived: false)]
}
現在,我嘗試調用一個API並返回與此完全相同的結構:
func GetLandGradingData(_ community: String, completion: @escaping (_ result: [GradingData]) -> Void)
{
let escapedCommunity = community.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
let urlComponents = NSURLComponents(string: webservice + "?community=" + escapedCommunity!);
urlComponents?.user = appDelegate.username;
urlComponents?.password = appDelegate.password;
let url = urlComponents?.url;
let returnedData = [GradingData]()
URLSession.shared.dataTask(with: url!, completionHandler: {
(data, response, error) in
if(error != nil){
completion(returnedData)
}else{
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [GradingData]
OperationQueue.main.addOperation({
completion(json)
})
}catch let error as NSError{
print(error)
completion(returnedData)
}
}
}).resume()
}
我的問題是方法沒有返回與getTestData方法相同的結構,附帶的是有關getTestData返回以及此api方法調用返回內容的屏幕截圖。
這是我的全班:
@objcMembers class GradingData : NSObject {
/**
Define lot Column String
*/
var lot: String?
/**
Define Address Column String
*/
var address: String?
/**
Define SLA Issued Final Grading Column String
*/
var SLAIssuedFinalGrading = false
/**
Define SLA Issued Final Grading Date Column String
*/
var SLAIssuedFinalGradingDate: String?
/**
Define City Approval Issued Column String
*/
var CityApprovalIssued = false
/**
Define City Comment Received Column String
*/
var CityCommentReceived = false
/**
Define Grading Repair Column String
*/
var GradingRepair: String?
/**
Define Curb Stop Repair Column String
*/
var CurbStopRepair: String?
/**
Define Splash Pad or Down Spout Column String
*/
var SplashPadDownSpout: String?
/**
Define RYCB or Other Repairs Column String
*/
var RYCBOtherRepairs: String?
/**
Define Comments Column String
*/
var Comments: String?
/**
Define Camera Column String
*/
var columnCamera: String?
/**
Define Deposit Received Column String
*/
var DepositReceived = false
/**
Inital call to class
*/
init(lot: String?, andColumns address: String?, SLAIssuedFinalGrading: Bool?, SLAIssuedFinalGradingDate: String?, CityApprovalIssued: Bool?, CityCommentReceived: Bool?, GradingRepair: String?, CurbStopRepair: String?, SplashPadDownSpout: String?, RYCBOtherRepairs: String?, Comments: String?, columnCamera: String?, DepositReceived: Bool?) {
super.init()
//Set lot string
self.lot = lot
//Set Address Column string
self.address = address
//Set SLA Issued Final Grading Column string
self.SLAIssuedFinalGrading = SLAIssuedFinalGrading!
//Set SLA Issued Final Grading Date Column string
self.SLAIssuedFinalGradingDate = SLAIssuedFinalGradingDate
//Set City Approval Issued Column string
self.CityApprovalIssued = CityApprovalIssued!
//Set City Comment Received Column string
self.CityCommentReceived = CityCommentReceived!
//Set Grading Repair Column string
self.GradingRepair = GradingRepair
//Set Curb Stop Repair Column string
self.CurbStopRepair = CurbStopRepair
//Set Splash Pad or Down Spout Column string
self.SplashPadDownSpout = SplashPadDownSpout
//Set RYCB or Other Repairs Column string
self.RYCBOtherRepairs = RYCBOtherRepairs
//Set Comments Column string
self.Comments = Comments
//Set Camera Column string
self.columnCamera = columnCamera
//Set Deposit Received Column string
self.DepositReceived = DepositReceived!
}
}
這是我來自API的數據:
<Reports>
<CityApprovalIssued>false</CityApprovalIssued>
<CityCommentReceived>false</CityCommentReceived>
<Comments></Comments>
<CurbStopRepair></CurbStopRepair>
<DepositReceived>false</DepositReceived>
<GradingRepair></GradingRepair>
<RYCBOtherRepairs></RYCBOtherRepairs>
<SLAIssuedFinalGrading>false</SLAIssuedFinalGrading>
<SLAIssuedFinalGradingDate/>
<SplashPadDownSpout></SplashPadDownSpout>
<address>123 Fake Street</address>
<lot>A0001</lot>
</Reports>
<Reports>
<CityApprovalIssued>false</CityApprovalIssued>
<CityCommentReceived>false</CityCommentReceived>
<Comments></Comments>
<CurbStopRepair></CurbStopRepair>
<DepositReceived>false</DepositReceived>
<GradingRepair></GradingRepair>
<RYCBOtherRepairs></RYCBOtherRepairs>
<SLAIssuedFinalGrading>false</SLAIssuedFinalGrading>
<SLAIssuedFinalGradingDate/>
<SplashPadDownSpout></SplashPadDownSpout>
<address>125 Fake Street</address>
<lot>A0002</lot>
</Reports>
這來自ASP.NET MVC API控制器: <ArrayOfReports xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/App.Models">
這是我在執行此操作時得到的:
let string = String(data: data!, encoding: .utf8)
print(string as Any)
Optional("[{\"lot\":\"A0001\",\"address\”:\”123 Fake Street\”,\”SLAIssuedFinalGrading\":false,\"SLAIssuedFinalGradingDate\":\"\",\"CityApprovalIssued\":false,\"CityCommentReceived\":false,\"GradingRepair\":\" \",\"CurbStopRepair\":\" \",\"SplashPadDownSpout\":\" \",\"RYCBOtherRepairs\":\" \",\"Comments\":\" \",\"DepositReceived\":false},{\"lot\":\"A0002\",\"address\":\"125 Fake Street\",\"SLAIssuedFinalGrading\":false,\"SLAIssuedFinalGradingDate\":\"\",\"CityApprovalIssued\":false,\"CityCommentReceived\":false,\"GradingRepair\":\" \",\"CurbStopRepair\":\" \",\"SplashPadDownSpout\":\" \",\"RYCBOtherRepairs\":\" \",\"Comments\":\" \",\"DepositReceived\":false}]")
首先,響應數據確實是JSON,XML輸出有點混亂。
您可能不需要從NSObject
繼承的類,在大多數情況下,尤其是在iOS中,一個結構就足夠了。
除了鍵columnCamera
之外,所有鍵都存在於所有記錄中,因此將所有屬性聲明為沒有默認值的非可選屬性,將columnCamera
聲明為可選的,並在不更改的情況下將所有屬性聲明為常量( let
)。
不需要顯式的init
方法。
添加了CodingKeys
以將大多數鍵轉換為小寫。
struct GradingData : Decodable {
private enum CodingKeys : String, CodingKey {
case lot, address, SLAIssuedFinalGrading
case SLAIssuedFinalGradingDate
case cityApprovalIssued = "CityApprovalIssued"
case cityCommentReceived = "CityCommentReceived"
case gradingRepair = "GradingRepair"
case curbStopRepair = "CurbStopRepair"
case splashPadDownSpout = "SplashPadDownSpout"
case RYCBOtherRepairs, comments = "Comments"
case columnCamera, depositReceived = "DepositReceived"
}
let lot: String
let address: String
let SLAIssuedFinalGrading : Bool
let SLAIssuedFinalGradingDate: String
let cityApprovalIssued : Bool
let cityCommentReceived : Bool
let gradingRepair : String
let curbStopRepair : String
let splashPadDownSpout : String
let RYCBOtherRepairs : String
let comments : String
let columnCamera : String?
let depositReceived : Bool
}
然后解碼JSON
....
var returnedData = [GradingData]()
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
if error != nil {
print(error!)
completion(returnedData)
} else {
do {
returnedData = try JSONDecoder().decode([GradingData].self, from: data!)
DispatchQueue.main.async {
completion(returnedData)
}
} catch {
print(error)
completion(returnedData)
}
}
}).resume()
只需將另一個init
添加到您的GradingData
模型類中,如下所示:
convenience init(data: [String : Any]) {
init(lot: data["lot"] as? String,
andColumns: data["address"] as? String,
SLAIssuedFinalGrading: data["SLAIssuedFinalGrading"] as? Bool,
SLAIssuedFinalGradingDate: data["SLAIssuedFinalGradingDate"] as? String,
CityApprovalIssued: data["CityApprovalIssued"] as? Bool,
CityCommentReceived: data["CityCommentReceived"] as? Bool,
GradingRepair: data["GradingRepair"] as? String,
CurbStopRepair: data["CurbStopRepair"] as? String,
SplashPadDownSpout: data["SplashPadDownSpout"] as? String,
RYCBOtherRepairs: data["RYCBOtherRepairs"] as? String,
Comments: data["Comments"] as? String,
columnCamera: data["columnCamera"] as? String,
DepositReceived: data["DepositReceived"] as? Bool)
}
在func GetLandGradingData(...)
方法中,將do { }
括號替換為以下內容:
let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [[String : Any]]
OperationQueue.main.addOperation({
let gradingDatas = json.map { GradingData(data: $0) }
completion(gradingDatas)
})
只是因為您要求一個示例(但沒有提供您的GradingData
才能使這個變得非常抽象):
struct GradingData : Codable {
// here is the meat, but you did not show ...
}
...
let grades = JSONDecoder().decode(GradingData.self, from: data)
Swift是我遇到的第一種釘住了它的語言。 它實際上只是歸結為一個接口的實現(大多數時間實際上沒有做任何有趣的事情,同時仍然提供了用最少的精力即可完成所有必要事情的可能性)並為您的對象獲得了免費的 JSON解析器(而不僅僅是一些垃圾郵件)字典)。
(稱為“進度” :-)
通過自定義類或nsxmlparser將XML轉換為字典。 或者如果您有分級數組,那么
var modelArr = [Grading]()
var model = Grading.init(fromDictionary dictionary: xmlParsedDic)
modelArr.append(model)
使用此模型類
import Foundation
class Grading : NSObject, NSCoding {
var cityApprovalIssued : Bool!
var cityCommentReceived : Bool!
var comments : String!
var curbStopRepair : String!
var depositReceived : Bool!
var gradingRepair : String!
var rYCBOtherRepairs : String!
var sLAIssuedFinalGrading : Bool!
var sLAIssuedFinalGradingDate : String!
var splashPadDownSpout : String!
var address : String!
var lot : String!
init(fromDictionary dictionary: [String:Any]){
cityApprovalIssued = dictionary["CityApprovalIssued"] as? Bool
cityCommentReceived = dictionary["CityCommentReceived"] as? Bool
comments = dictionary["Comments"] as? String
curbStopRepair = dictionary["CurbStopRepair"] as? String
depositReceived = dictionary["DepositReceived"] as? Bool
gradingRepair = dictionary["GradingRepair"] as? String
rYCBOtherRepairs = dictionary["RYCBOtherRepairs"] as? String
sLAIssuedFinalGrading = dictionary["SLAIssuedFinalGrading"] as? Bool
sLAIssuedFinalGradingDate = dictionary["SLAIssuedFinalGradingDate"] as? String
splashPadDownSpout = dictionary["SplashPadDownSpout"] as? String
address = dictionary["address"] as? String
lot = dictionary["lot"] as? String
}
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if cityApprovalIssued != nil{
dictionary["CityApprovalIssued"] = cityApprovalIssued
}
if cityCommentReceived != nil{
dictionary["CityCommentReceived"] = cityCommentReceived
}
if comments != nil{
dictionary["Comments"] = comments
}
if curbStopRepair != nil{
dictionary["CurbStopRepair"] = curbStopRepair
}
if depositReceived != nil{
dictionary["DepositReceived"] = depositReceived
}
if gradingRepair != nil{
dictionary["GradingRepair"] = gradingRepair
}
if rYCBOtherRepairs != nil{
dictionary["RYCBOtherRepairs"] = rYCBOtherRepairs
}
if sLAIssuedFinalGrading != nil{
dictionary["SLAIssuedFinalGrading"] = sLAIssuedFinalGrading
}
if sLAIssuedFinalGradingDate != nil{
dictionary["SLAIssuedFinalGradingDate"] = sLAIssuedFinalGradingDate
}
if splashPadDownSpout != nil{
dictionary["SplashPadDownSpout"] = splashPadDownSpout
}
if address != nil{
dictionary["address"] = address
}
if lot != nil{
dictionary["lot"] = lot
}
return dictionary
}
@objc required init(coder aDecoder: NSCoder)
{
cityApprovalIssued = aDecoder.decodeObject(forKey: "CityApprovalIssued") as? Bool
cityCommentReceived = aDecoder.decodeObject(forKey: "CityCommentReceived") as? Bool
comments = aDecoder.decodeObject(forKey: "Comments") as? String
curbStopRepair = aDecoder.decodeObject(forKey: "CurbStopRepair") as? String
depositReceived = aDecoder.decodeObject(forKey: "DepositReceived") as? Bool
gradingRepair = aDecoder.decodeObject(forKey: "GradingRepair") as? String
rYCBOtherRepairs = aDecoder.decodeObject(forKey: "RYCBOtherRepairs") as? String
sLAIssuedFinalGrading = aDecoder.decodeObject(forKey: "SLAIssuedFinalGrading") as? Bool
sLAIssuedFinalGradingDate = aDecoder.decodeObject(forKey: "SLAIssuedFinalGradingDate") as? String
splashPadDownSpout = aDecoder.decodeObject(forKey: "SplashPadDownSpout") as? String
address = aDecoder.decodeObject(forKey: "address") as? String
lot = aDecoder.decodeObject(forKey: "lot") as? String
}
@objc func encode(with aCoder: NSCoder)
{
if cityApprovalIssued != nil{
aCoder.encode(cityApprovalIssued, forKey: "CityApprovalIssued")
}
if cityCommentReceived != nil{
aCoder.encode(cityCommentReceived, forKey: "CityCommentReceived")
}
if comments != nil{
aCoder.encode(comments, forKey: "Comments")
}
if curbStopRepair != nil{
aCoder.encode(curbStopRepair, forKey: "CurbStopRepair")
}
if depositReceived != nil{
aCoder.encode(depositReceived, forKey: "DepositReceived")
}
if gradingRepair != nil{
aCoder.encode(gradingRepair, forKey: "GradingRepair")
}
if rYCBOtherRepairs != nil{
aCoder.encode(rYCBOtherRepairs, forKey: "RYCBOtherRepairs")
}
if sLAIssuedFinalGrading != nil{
aCoder.encode(sLAIssuedFinalGrading, forKey: "SLAIssuedFinalGrading")
}
if sLAIssuedFinalGradingDate != nil{
aCoder.encode(sLAIssuedFinalGradingDate, forKey: "SLAIssuedFinalGradingDate")
}
if splashPadDownSpout != nil{
aCoder.encode(splashPadDownSpout, forKey: "SplashPadDownSpout")
}
if address != nil{
aCoder.encode(address, forKey: "address")
}
if lot != nil{
aCoder.encode(lot, forKey: "lot")
}
}}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.