我正在try 用AlamoFire从服务器上解析数据.

(我已经试了两天了,但失败了.) 我怎样才能用Alamofire得到Json数组可编码类型?

接口:不,不,不.

[ { "姓名":"无名氏", "Email":"johndoe@gmail.com", "type":"Lattee", "Size":"中等" }, { "姓名":"无名氏", "Email":"doe@gmail.com", "type":"Lattee", "Size":"小" } ]

这是我的代码

在Model.SWIFT中

struct OrderList : Codable{
    var list : [Order]
}

enum coffeeType: String, Codable{
    case cappuccino
    case lattee
    case espressino
    case cortado
    
}
enum coffeeSize: String, Codable{
    case small
    case medium
    case large
    
    enum CodingKeys: String, CodingKey {
        case small = "s"
        case medium = "m"
        case large = "l"
    }
}
struct Order: Codable {
    let email: String!
    let name : String!
    let size : coffeeSize!
    let type : coffeeType!
    
    enum CodingKeys: String, CodingKey{
        case name = "Name"
        case email = "Email"
        case type  = "Type"
        case size  = "Size"
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        email = try values.decodeIfPresent(String.self, forKey: .email) ?? ""
        name  = try values.decodeIfPresent(String.self, forKey: .name)  ?? "Guest"
        size  = try values.decodeIfPresent(coffeeSize.self, forKey: .size) ?? .small
        type  = try values.decodeIfPresent(coffeeType.self, forKey: .type) ?? .lattee
    }
}

struct Resource<T: Codable> {
    let url       : URL
    var httpMethod: HTTPMethod = .get
}

我用不同的格式定义了它,比如响应数据、响应JSON和响应编码,但是我总是得不到任何东西,或者缺少一些东西. 我知道如何使用ResponseJSON进行解析.但我想试着通过应用可编码的. 这太难了.

-数据解析


func load<T>(resource: Resource<T>, completion: @escaping (Result<T, NetworkError>) -> Void) {
        let call = AF.request(myurl,method: resource.httpMethod, parameters: nil).responseJSON{ response in
            switch response.result {
            case .success(let data):
                if let JSON = response.value {
                    do{
                       let dataJson = try JSONSerialization.data(withJSONObject: JSON, options: [])
                        let getInstanceData = try JSONDecoder().decode(T.self, from: dataJson)
                        print(getInstanceData)
                        completion(.success(getInstanceData))
                        
                    }catch{
                        print(error)
                    }
                }
            case .failure(_):
                
                break
            }
        }
    }

推荐答案

由于API返回此有效负载:

[ { "name": "John Doe", "email": "johndoe@gmail.com", "type": "Lattee", "size": "medium" }, { "name": "Doe", "email": "doe@gmail.com", "type": "Lattee", "size": "small" } ]

以下是您的代码需要处理的键: nameemailtypesize

因此,Order struct 应该是:

struct Order: Codable {
    let email: String
    let name : String
    let size : CoffeeSize
    let type : CoffeeType
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        email = try values.decodeIfPresent(String.self, forKey: .email) ?? ""
        name  = try values.decodeIfPresent(String.self, forKey: .name)  ?? "Guest"
        size  = try values.decode(CoffeeSize.self, forKey: .size)
        type  = try values.decode(CoffeeType.self, forKey: .type)
    }
}

enum CoffeeType: String, Codable {
    case cappuccino
    case latte
    case espressino
    case cortado
   
    init(from decoder: Decoder) throws {
        let label = try decoder.singleValueContainer().decode(String.self)
        let lowercaseLabel = label.lowercased()
        self = CoffeeType(rawValue: lowercaseLabel) ?? .latte
    }
}

enum CoffeeSize: String, Codable {
    case small
    case medium
    case large
}

因为在json struct 中没有list键,所以您不需要 struct OrderList.为了获得订单列表,您只需调用

load(resource<[Order]>) { result in
   // handle the response but now you will get the list of orders
}

或者,我创建了一个playground ,在本地加载一个json文件(data.json)并将其解析为对象,您可以查看下面的解决方案

func readJsonFile(filename: String) -> String {
    guard let fileUrl = Bundle.main.url(forResource: filename, withExtension: "json") else { fatalError() }
    guard let jsonData = try? String(contentsOf: fileUrl) else {
        return ""
    }
    return jsonData
}

enum CoffeeType: String, Codable {
    case cappuccino
    case latte
    case espressino
    case cortado
   
    init(from decoder: Decoder) throws {
        let label = try decoder.singleValueContainer().decode(String.self)
        let lowercaseLabel = label.lowercased()
        self = CoffeeType(rawValue: lowercaseLabel) ?? .latte
    }
}

enum CoffeeSize: String, Codable {
    case small
    case medium
    case large
}

struct Order: Codable {
    let email: String
    let name : String
    let size : CoffeeSize
    let type : CoffeeType
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        email = try values.decodeIfPresent(String.self, forKey: .email) ?? ""
        name  = try values.decodeIfPresent(String.self, forKey: .name)  ?? "Guest"
        size  = try values.decode(CoffeeSize.self, forKey: .size)
        type  = try values.decode(CoffeeType.self, forKey: .type)
    }
}

func parseJsonFile() {
    let jsonStr = readJsonFile(filename: "data")
    let jsonData: Data = Data(jsonStr.utf8)
    let decoder = JSONDecoder()
    do {
        let orders = try decoder.decode([Order].self, from: jsonData)
        orders.forEach {
            print("\($0.name)" + " - " + "\($0.type.rawValue)" + " - " + "\($0.size.rawValue)")
        }
    } catch {
        print(error.localizedDescription)
    }
}

parseJsonFile()

结果:

John Doe - latte - medium
Doe - latte - small

Ios相关问答推荐

Firebase SDK 10+—无法安装软件包

SWIFT中具有可选返回类型和泛型的网络请求

XcodeCloud生成失败,返回";ci_pre_xcodeBuild.sh是可执行文件,但退出时返回2个退出代码.";

withTaskGroup不适用于CLGeocoder

swift|在具有自定义单元格的多个TableView中没有任何内容

SwiftUI:.toolbar 不适用于 UITextView

多协议和类继承混乱,Swift

应用程序被杀死时如何在 flutter ios 应用程序中播放音频?

如何为 XCTest、SwiftUI 预览等初始化带有 @MainActor 注释的 Swift 类

具有多个目标的应用程序的动态内容

将图像保存到 Documents 目录并检索邮箱附件

如何在 UIActivityViewController 中设置邮件主题?

Xcode 4.1 致命错误:自构建预编译头文件后修改了 stdlib

为信用卡输入格式化 UITextField,例如 (xxxx xxxx xxxx xxxx)

关闭通过模态 segue 显示的视图

iOS UITextView 或 UILabel 带有可点击的动作链接

单击 GoogleSignIn 按钮时应用程序崩溃

在 iOS 上编写文件

如何删除 Swift 数组中的所有 nil 元素?

具有两种不同字体大小的 NSAttributedString 示例?