簡體   English   中英

Swift將JSON解析為模型對象

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM