Swift5:如何将此 JSON 响应处理为 Swift 数据模型

Swift5 : How to handle this JSON response into Swift Data Model

我是 Swift 的新手,所以如果这是一个愚蠢的问题,请原谅我 如何将这种类型的响应处理成数据模型,响应是这样的形式:

{
    "id" = 1;
    count = "";
    data = "[{"key":"value","key":"value".......}]";
    message = SUCCESS;
    "response_code" = 1;
}

AlamofireRequest 获取响应并打印它但是当使用 responseDecodable 时,没有任何反应,Alamofire 请求的代码如下:

let request = AF.request(urlString!,method: .get)
        
request.responseJSON { (data) in
  print(data)
}
        
request.responseDecodable(of: Test.self) { (response) in 
    guard let getData = response.value else {return}
    print(getData.all[0].firstName)  //Nothing prints
}

这就是数据模型的样子:

struct Test: Decodable {
   
    let firstName: String

    enum CodingKeys: String, CodingKey {
        case firstName = "first_name" 
        //firstname is inside data of json
    }
}

struct Getdata: Decodable {
    let all : [Test]
    
    enum CodingKeys: String, CodingKey {
        case all = "data"
    }
}

想要访问数据中的值并打印它。请说明一下!

尝试解决上面的问题和评论,首先要获得一些有效的 JSON。可能是您的 API 正在提供 non-JSON 数据,在这种情况下,此答案或使用 AlamoFire 对其进行解码都不起作用。然而,将上面的格式设置为 JSON,在我最好的猜测中,将给出:

let json = """
{
  "id": 1,
  "count": "",
  "data": [
    {
      "key1": "value1",
      "key2": "value2"
    }
  ],
  "message": "SUCCESS",
  "response_code": 1
}
"""

此时更明显的是data键下的内容不是上面定义的Test数组,而是一个字典数组(数组中只有一个条目在示例中)。因此,有必要重新指定数据模型。对于这么简单的事情,对于提到的用例,没有真正的理由去使用多种类型,所以我们将重新定义 Getdata(尽管不喜欢,我还是坚持你的命名):

struct Getdata: Decodable {
   let all : [[String:String]]
   
   enum CodingKeys: String, CodingKey {
      case all = "data"
   }
}

为了测试解码,让我们使用标准的 JSON解码器(我手头没有 AlamoFire 的 Playground,因为我从来没有用过它):


do {
   let wrapper = try JSONDecoder().decode(Getdata.self, from: Data(json.utf8))
   print(wrapper.all)
} catch {
   print("Decoding error \(error.localizedDescription)")
}

这输出

[["key1": "value1", "key2": "value2"]]

符合预期。

现在有一个有效的 JSON 解码解决方案,如果您愿意,将它放入 AlamoFire API 应该很容易。尽管如果后端确实提供了所讨论的格式错误的 JSON,这将不起作用,您将不得不更改后端,使用您自己的解码器对其进行解码,或者将其分解为有效的 JSON。

原题犯了很多愚蠢的错误,还有很长的路要走

按照@flanker 的建议,我确实将数据模型重新指定为

struct Test : Codable {
    let id : String?
    let message : String?
    let data : String?
    let count : String?
    let response_code : String?

    enum CodingKeys: String, CodingKey {

        case id = "$id"
        case message = "message"
        case data = "data"
        case count = "count"
        case response_code = "response_code"
    }
       init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decodeIfPresent(String.self, forKey: .id)
        message = try values.decodeIfPresent(String.self, forKey:  .message)
        data = try values.decodeIfPresent(String.self, forKey: .data)
        count = try values.decodeIfPresent(String.self, forKey: .count)
        response_code = try values.decodeIfPresent(String.self, forKey: .response_code)
    }

现在好像可以了

现在得到了想要的输出 [["key1": "value1", "key2": "value2"]]