将JSON数组投射到结构模型swift

问题描述 投票:0回答:2

我正在将对象的json数组解析为有效的模型。在此对象中,有一个值数组,我创建了另一个模型来处理该数组,但是每当我传递该对象时,内部数组在转换为模型类后都将返回nil。任何帮助表示赞赏

JSON样本

[
    {
        "code": "AF",
        "code3": "AFG",
        "dial_code": "+93",
        "name": "Afghanistan",
        "capital": "Kabul",
        "region": "Asia",
        "subregion": "Southern Asia",
        "states": [
            {
                "code": "BDS",
                "name": "Badakhshān",
                "subdivision": null
            },
            {
                "code": "BGL",
                "name": "Baghlān",
                "subdivision": null
            }
        ]
    }
 }

]

MODEL

public struct LocaleInfo {

    public var locale: Locale?

    public var id: String? {
        return locale?.identifier
    }

    public var country: String
    public var code: String
//    public var phoneCode: String
    public var states: [LocalStateInfo]

    public var flag: UIImage? {
        return UIImage(named: "Countries.bundle/Images/\(code.uppercased())", in: Bundle.main, compatibleWith: nil)
    }

    public var currencyCode: String? {
        return locale?.currencyCode
    }

    public var currencySymbol: String? {
        return locale?.currencySymbol
    }

    public var currencyName: String? {
        guard let currencyCode = currencyCode else { return nil }
        return locale?.localizedString(forCurrencyCode: currencyCode)
    }

    init(country: String, code: String/*, phoneCode: String*/, states: [LocalStateInfo]) {
        self.country = country
        self.code = code
        self.states = states
        self.locale = Locale.availableIdentifiers.map { Locale(identifier: $0) }.first(where: { $0.regionCode == code })
    }
}

public struct LocalStateInfo {
     public var code: String
     public var name: String
     public var subdivision: String
}

传递JSON主体

func getInfo(completionHandler: @escaping (FetchResults) -> ()) {
        let bundle = Bundle(for: LocalePickerViewController.self)
        let path = "Countries.bundle/Data/CountryCodes"

        guard let jsonPath = bundle.path(forResource: path, ofType: "json"),
            let jsonData = try? Data(contentsOf: URL(fileURLWithPath: jsonPath)) else {
                let error: (title: String?, message: String?) = (title: "ContryCodes Error", message: "No ContryCodes Bundle Access")
                return completionHandler(FetchResults.error(error: error))
        }

        if let jsonObjects = (try? JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.allowFragments)) as? Array<Any> {
            var result: [LocaleInfo] = []
            for jsonObject in jsonObjects {
                guard let countryObj = jsonObject as? Dictionary<String, Any> else { continue }
                guard let country = countryObj["name"] as? String,
                    let code = countryObj["code"] as? String/*,
                    let phoneCode = countryObj["dial_code"] as? String*/ else {
                        fatalError("Broken here")
                        continue
                }
                log("countryObj state \(countryObj["states"] as? [LocalStateInfo])", .fuck)
                log("countryObj \(countryObj)", .fuck)

                let states = countryObj["states"] as? [LocalStateInfo] ?? [LocalStateInfo]()
                let new = LocaleInfo(country: country, code: code/*, phoneCode: phoneCode*/, states: states)
                result.append(new)
            }
            return completionHandler(FetchResults.success(response: result))
        }

        let error: (title: String?, message: String?) = (title: "JSON Error", message: "Couldn't parse json to Info")
        return completionHandler(FetchResults.error(error: error))
    }
swift
2个回答
0
投票
let states = countryObj["states"] as? [LocalStateInfo] ?? [LocalStateInfo]()

大概是不适合您的行。但是countryObj只是直接来自JSON的字典:

guard let countryObj = jsonObject as? Dictionary<String, Any> else { continue }

为什么将其强制转换为LocalStateInfo数组完全起作用?它是一个字典数组,您需要分别解析每个字典。

[您曾说过使用Codable会改变库的“整个范围”,我不知道是这种情况。您可以实现可编码(甚至只是Decodable),而不会影响任何其他文件。


0
投票

您需要

guard let res = jsonObject as? [[String:Any]] else { return }
© www.soinside.com 2019 - 2024. All rights reserved.