【问题标题】:How to create struct and init values from GET url in swift如何在 swift 中从 GET url 创建 struct 和 init 值
【发布时间】:2020-03-15 20:52:17
【问题描述】:

我的 JSON:

   {
  "id": "70",
  "bname": "Municipal Corporation - Water",
  "bcategoryname": "Water",
  "bcustomerparms": "[{\"paramName\":\"Consumer Number\",\"dataType\":\"NUMERIC\",\"optional\":\"false\",\"minLength\":\"1\",\"maxLength\":\"10\" .      },
           {\"paramName\":\"Mobile Number\",\"dataType\":\"NUMERIC\",\"optional\":\"false\",\"minLength\":\"10\",\"maxLength\":\"10\"},
           {\"paramName\":\"Email . Id\",\"dataType\":\"ALPHANUMERIC\",\"optional\":\"false\",\"minLength\":\"5\",\"maxLength\":\"100\"}]",
 }
  {    
 "id": "68",
 "bname": "Municipal Corporation - 12",
 "bcategoryname": "Water",
 "bcustomerparms": "[{\"paramName\":\"K No\",\"dataType\":\"ALPHANUMERIC\",\"optional\":\"false\",\"minLength\":\"7\",\"maxLength\":\"20\"}]",
 } 

我无法从 get api 创建结构,我需要根据 bcategoryname 的 bname 和它的 paramNamew,我需要在 table 中显示 bname,如果我选择我需要它的所有 paramNames。

代码如下:

struct JsonDataBiller{
var bname: String?
var bcategoryname: String?
var bcustomerparms: [cDetails]

init(bname: String, bcategoryname: String, bcustomerparms: [cDetails]){

    self.bname = bname
    self.bcategoryname = bcategoryname
    self.bcustomerparms = bcustomerparms
}
}

struct cDetails{
var paramName: String?
var minLength: String?
var maxLength: String?

init(paramName: String, minLength: String, maxLength: String)
{
    self.paramName = paramName
    self.minLength = minLength
    self.maxLength = maxLength
}
}

代码:

class AllMakePaymentViewController: UIViewController {

@IBOutlet weak var tableView: UITableView!

var jsonData = [JsonDataBiller]()

var minLength: String?
var maxLength: String?
var bName: String?
var category: Category?
var categoryName: String?
var paramName: String?

var ParamArray = [String]()

var labelText: String?
override func viewDidLoad() {
    super.viewDidLoad()

    allPaymentService()
}

func allPaymentService(){

    let urlStr = "https://dev.anyemi.com/webservices/anyemi/api.php?rquest=billermdm"
    let url = URL(string: urlStr)
    URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
        guard let respData = data else {
            return
        }
        guard error == nil else {
            print("error")
            return
        }
        do{
            let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
            //print("the all make payment json is \(jsonObj)")
            let billerdetailsArray = jsonObj["billerdetails"] as! [[String: Any]]

            for billerdetail in billerdetailsArray {

                self.categoryName = billerdetail["bcategoryname"] as? String

                let customrParams = billerdetail["bcustomerparms"] as! String
                let res = try JSONSerialization.jsonObject(with:Data(customrParams.utf8)) as! [[String: Any]]

                for item in res {

                    self.paramName = item["paramName"] as? String

                    self.minLength = item["minLength"] as? String
                    self.maxLength = item["maxLength"] as? String
                                            if self.categoryName == "Water"{
                        let bName = billerdetail["bname"] as? String
                        self.jsonData.append(JsonDataBiller(bname: bName ?? "", bcategoryname: self.categoryName ?? "", bcustomerparms: [paramName: paramName, minLength: minLength, maxLength: maxLength]))

                    }
                    if self.categoryName == "Electricity"{
                        let bName = billerdetail["bname"] as? String
                        self.jsonData.append(JsonDataBiller(bname: bName ?? "", bcategoryname: self.categoryName ?? "", bcustomerparms: [paramName: paramName, minLength: minLength, maxLength: maxLength]))
                    }
                }
            }
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }catch {
            print("catch error")
        } }).resume()
}
}

错误:

上下文类型 '[cDetails]' 不能与字典文字一起使用

这里我需要根据其bcategoryname添加bnam和根据bname添加paramName

请在上面的代码中帮助我,我无法解决这个问题,我卡住了很长时间。

【问题讨论】:

  • 你应该使用 Codable... 如果你使用它,事情会简单得多
  • @SchaheerSaleem,请发布如何编码的答案
  • 谷歌如何使用 Codable 协议解析 JSON。这是很棒的教程raywenderlich.com/3418439-encoding-and-decoding-in-swift
  • @swift json 格式不正确
  • 错误发生在哪里?

标签: ios json swift dictionary get


【解决方案1】:

如果您正在努力创建结构,您可以尝试使用这个网站,它会自动完成:

https://app.quicktype.io/

*不过,我还是建议先理解这个概念,然后再使用这样的助手

在您的情况下,您的 JSON 文件存在问题。

您的 JSON 的第一部分应该如下所示:

{ “身份证”:70, “bname”:“市政公司 - 水”, "bcategoryname": "水", “bcustomerparms”:[ { "paramName": "消费者编号", “数据类型”:“数字”, “可选”:假, “最小长度”:1, “最大长度”:10} ] }

// MARK: - DataStructure
struct DataStructure: Codable {
    let id: Int
    let bname, bcategoryname: String
    let bcustomerparms: [Bcustomerparm]
}

// MARK: - Bcustomerparm

struct Bcustomerparm: Codable {
    let paramName, dataType: String
    let bcustomerparmOptional: Bool
    let minLength, maxLength: Int

enum CodingKeys: String, CodingKey {
    case paramName, dataType
    case bcustomerparmOptional = "optional"
    case minLength, maxLength
}

}

【讨论】:

    【解决方案2】:

    你越来越近了……

    关键步骤问题是您正在遍历“客户参数”并为每个参数添加一个新客户对象,而不是添加 一个 包含的客户对象参数数组。

    看看这个 - 它应该在没有任何编辑的情况下运行。解析数据后,它将打印 Water 客户列表及其相关参数。

    调试输出应如下所示:

    Water count: 18
    Electricity count: 71
    
    Name: Bhopal Municipal Corporation - Water
    Cat:  Water
    Param: Connection ID / minLength: 8 / maxLength: 8
    
    Name: Bangalore Water Supply and Sewerage Board
    Cat:  Water
    Param: RR Number / minLength: 8 / maxLength: 8
    
    Name: Delhi Jal Board
    Cat:  Water
    Param: K No / minLength: 10 / maxLength: 10
    
    ...
    
    Name: Municipal Corporation Jalandhar
    Cat:  Water
    Param: Account No / minLength: 1 / maxLength: 1
    Param: Consumer Mobile No / minLength: 10 / maxLength: 10
    Param: Consumer Email ID / minLength: 5 / maxLength: 5
    Param: UID / minLength: 1 / maxLength: 1
    
    Name: Municipal Corporation Ludhiana - Water
    Cat:  Water
    Param: Consumer Number / minLength: 1 / maxLength: 1
    Param: Mobile Number / minLength: 10 / maxLength: 10
    Param: Email Id / minLength: 5 / maxLength: 5
    
    Name: New Delhi Municipal Council (NDMC) - Water
    Cat:  Water
    Param: Consumer Number / minLength: 7 / maxLength: 7
    
    ...
    

    这里是来源:

    //    
    import UIKit
    
    struct JsonDataBiller{
        var bname: String?
        var bcategoryname: String?
        var bcustomerparms: [cDetails]
    
        init(bname: String, bcategoryname: String, bcustomerparms: [cDetails]){
    
            self.bname = bname
            self.bcategoryname = bcategoryname
            self.bcustomerparms = bcustomerparms
        }
    }
    
    struct cDetails{
        var paramName: String?
        var minLength: String?
        var maxLength: String?
    
        init(paramName: String, minLength: String, maxLength: String)
        {
            self.paramName = paramName
            self.minLength = minLength
            self.maxLength = maxLength
        }
    }
    
    class AllMakePaymentViewController: UIViewController {
    
        // arrays of JsonDataBiller objects for each category
        var jsonWaterData = [JsonDataBiller]()
        var jsonElectricityData = [JsonDataBiller]()
        // ...
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            allPaymentService()
        }
    
        func allPaymentService(){
    
            let urlStr = "https://dev.anyemi.com/webservices/anyemi/api.php?rquest=billermdm"
            let url = URL(string: urlStr)
            URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
    
                guard let respData = data else {
                    return
                }
                guard error == nil else {
                    print("error")
                    return
                }
                do{
                    let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any]
                    //print("the all make payment json is \(jsonObj)")
                    let billerdetailsArray = jsonObj["billerdetails"] as! [[String: Any]]
    
                    for billerdetail in billerdetailsArray {
    
                        // make these local vars --- no need for the confusing self. properties
                        let localBName = billerdetail["bname"] as? String ?? ""
                        let localCName = billerdetail["bcategoryname"] as? String  ?? ""
    
                        let customrParams = billerdetail["bcustomerparms"] as! String
                        let res = try JSONSerialization.jsonObject(with:Data(customrParams.utf8)) as! [[String: Any]]
    
                        // create new array of cDetails objects
                        var aParams = [cDetails]()
    
                        // for each param item
                        for item in res {
    
                            if let pn = item["paramName"] as? String,
                                let minL = item["minLength"] as? String,
                                let maxL = item["maxLength"] as? String {
    
                                // create new cDetails object
                                let cd = cDetails(paramName: pn, minLength: minL, maxLength: maxL)
    
                                // append it to the aParams array
                                aParams.append(cd)
    
                            }
    
                        }
    
                        // create new JsonDataBiller object with
                        //      bname
                        //      bcategoryname
                        //      array of bcustomerparms
                        let jdBiller = JsonDataBiller(bname: localBName,
                                                      bcategoryname: localCName,
                                                      bcustomerparms: aParams)
    
                        // append the JsonDataBiller object to the appropriate category array
                        if localCName == "Water" {
                            self.jsonWaterData.append(jdBiller)
                        }
                        if localCName == "Electricity" {
                            self.jsonElectricityData.append(jdBiller)
                        }
                        // if localCName == ...
    
                    }
    
                    // finished parsing the data into arrays of jdBiller objects
                    print("Water count: \(self.jsonWaterData.count)")
                    print("Electricity count: \(self.jsonElectricityData.count)")
                    print()
    
                    // for quick debugging...
                    self.jsonWaterData.forEach {
                        obj in
                        print("Name: \(obj.bname ?? "")")
                        print("Cat:  \(obj.bcategoryname ?? "")")
                        obj.bcustomerparms.forEach {
                            param in
                            print("Param: \(param.paramName ?? "") / minLength: \(param.minLength ?? "") / maxLength: \(param.minLength ?? "")")
                        }
                        print()
                    }
    
    //              DispatchQueue.main.async {
    //                  self.tableView.reloadData()
    //              }
    
                }catch {
                    print("catch error")
                } }).resume()
        }
    }
    

    【讨论】:

    • 非常感谢您...您的解决方案很完美,请在这里对您的答案做一个小扩展...我卡在这里很久了,请在这里帮助我...我是jr 开发人员我无法解决这个问题。stackoverflow.com/questions/58939991/…
    • 如何将所有三个参数值发送到下一个视图控制器,我只能发送一个参数并且与 bname 无关
    • @swift - 好的,我根据答案中的解析方法对您的项目进行了更改。如果您访问您的 GitHub 存储库并选择 Options -> Collaborators 并添加我(我的 GitHub id 是“DonMag”),我可以推送我的更改,以便您查看差异。
    • 先生,您可以推送我添加您的代码.. github.com/SwiftSamples/HomeIssue/invitations
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 2015-07-28
    相关资源
    最近更新 更多