我的结构不适用于可解码的

时间:2018-03-22 20:00:01

标签: ios json swift

一直使用swift 3,直到我更新了我的Xcode,它附带了swift 4,并且我必须开始使用可编码的可解码,但我很难生成结构来解码。这是json我试图变成一个对象

{
    "status": "true",
    "message": "Valid request",
    "data": {
        "user_id": "16",
        "first_name": "Hamidouh",
        "last_name": "Semix",
        "other_name": null,
        "fullname": "Hamidouh Semix",
        "alias": null,
        "about": "",
        "sex_id": "1",
        "sex": "Male",
        "birth_date": "1989-08-17 00:00:00",
        "relation_status_id": null,
        "relation_status": null,
        "relation_user_id": null,
        "relation_user_first_name": null,
        "relation_user_last_name": null,
        "relation_user_fullname": null,
        "location": null,
        "contact": null,
        "profile_pic": "698",
        "profile_folder_name": "profile-picture",
        "profile_pic_filename": "PROFILE-IMG-UPLOAD-1-16-20171222101217.jpg",
        "cover_pic": "697",
        "cover_folder_name": "cover-picture",
        "cover_pic_filename": "COVER-IMG-UPLOAD-1-16-20171222100128.png",
        "followers_list": {
            "user_11": {
                "id": "11",
                "datetime": "2018-02-20 19:09:44"
            }
        },
        "following_list": {
            "user_1": {
                "id": "1",
                "datetime": "2018-03-01 09:53:24"
            },
            "user_3": {
                "id": "3",
                "datetime": "2018-02-19 09:18:18"
            },
            "user_24": {
                "id": "24",
                "datetime": "2017-12-22 09:58:17"
            },
            "user_260": {
                "id": "260",
                "datetime": "2018-02-19 09:18:16"
            }
        },
        "mutual_list": {
            "user_78": {
                "id": "78",
                "datetime": "2017-12-08 12:05:23"
            }
        },
        "request_counter": "0",
        "dream_destination_list": null,
        "hidden_content_list": null,
        "email": "semixss.hamidouh@gmail.com",
        "username": null,
        "password": "84bcec2f89a4f8cdd17b4a98d1a6cbf69bc9efe657d36a09b2d423fa3030772ab8ba9e24",
        "salt": "owkLO",
        "social_media_auth": null,
        "social_media_id": null,
        "date_created": "2017-08-18 14:00:22",
        "last_seen": "2018-03-16 13:53:57",
        "is_suspended": null,
        "is_notified": null,
        "approve_token": "8f82fbac62ded7260a3faa45460719a1390e3e216c6ebf3c4794f2da627138b9",
        "device_token": null,
        "language_id": null,
        "language_machine_name": null,
        "language_label": null,
        "active": "1"
    }
}

目前这些是我能够为json

生成的结构
struct user : Decodable {
    let status: String
    let message: String
    let data: userData
}

struct userData : Decodable {

    let user_id: Int
    let first_name: String
    let last_name: String
    let other_name: String
    let fullname: String
    let alias: String
    let about: String
    let sex_id: Int
    let sex: String
    let birth_date: String
    let relation_status_id: Int
    let relation_status: String
    let relation_user_id: Int
    let relation_user_first_name: String
    let relation_user_last_name: String
    let relation_user_fullname: String
    let location: String
    let contact: String
    let profile_pic: Int
    let profile_folder_name: String
    let profile_pic_filename: String
    let cover_pic: Int
    let cover_folder_name: String
    let cover_pic_filename: String
    let followers_list: Int
    let following_list: Int
    let mutual_list: Int
    let request_counter: Int
    let dream_destination_list: Int
    let hidden_content_list: Int
    let email: String
    let username: String
    let password: String
    let salt: String
    let social_media_auth: String
    let social_media_id: Int
    let date_created: String
    let last_seen: String
    let is_suspended: String
    let is_notified: String
    let approve_token: String
    let device_token: String
    let language_id: Int
    let language_machine_name: String
    let language_label: String
    let active: Int

}
  

这是我为尝试解析此

而编写的解码代码
//send request to server

guard let loginUrl = URL(string: "https://xxxxxx.com/api/index.php/Auth/login") else {return}

//request url
var request = URLRequest(url: loginUrl)

// method to pass data
request.httpMethod = "POST"

let body = "username=\(usernameVar)&password=\(passwordVar)"
request.httpBody = body.data(using: String.Encoding.utf8)

//launch session
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in

    guard let data = data else {return}

    do {
        //let json = try JSONSerialization.jsonObject(with: data, options: [])
        //print(json)
      let userDetails = try JSONDecoder().decode(user.self, from: data)
      for details in userDetails  {
        print(details.message)
      }

    }catch{
        print(error)
    }
  }

  task.resume()

这是错误

typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[],debugDescription:"期望解码数组,但却找到了一个字典。",underlyingError:nil))

1 个答案:

答案 0 :(得分:0)

您应该将错误消息更改为更有用的错误消息Lol。

您还没有在json中考虑可选值。请记住,StringString?之间存在差异,json有效内容中有多个值返回nil。在swift结构中,您需要将这些字段标记为Optionals

您也有不匹配的类型。您返回的所有类型均为StringString?而非Int。这些只是String?返回的数字。此有效负载中也嵌套了Dictionary种类型。 followers_list是一个字典,因此您需要使用名为List的属性创建一个新结构,并在UserData结构中设置这些"列表"的类型。到[String:List]

当您对解码时抛出的错误类型(以及大多数CocoaTouch Framework)感到困惑时,这些错误都是NSErrors。您可以将错误的值打印到控制台,它会准确地告诉您退出示波器的错误。 IE:

 valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [__lldb_expr_20.user.(CodingKeys in _992B1F7B4C3E0BAC48AEA280B9410D72).data, __lldb_expr_20.userData.,
debugDescription: "Expected String value but found null instead.", underlyingError: nil))

上述错误消息告诉您CodingKey...userData设置为期待String,但有null(无)。

下面是你当前的结构应该是什么样的:

struct User : Decodable {
     let status: String
     let message: String
     let data: userData
 }

 struct List: Decodable {
    var id: String?
    var datetime: String?
 }

struct UserData : Decodable {

let user_id: String 
let first_name: String
let last_name: String
let other_name: String? 
let fullname: String
let alias: String? 
let about: String
let sex_id: String 
let sex: String
let birth_date: String
let relation_status_id: String? 
let relation_status: String?
let relation_user_id: String?
let relation_user_first_name: String?
let relation_user_last_name: String?
let relation_user_fullname: String?
let location: String?
let contact: String?
let profile_pic: String
let profile_folder_name: String
let profile_pic_filename: String
let cover_pic: String
let cover_folder_name: String
let cover_pic_filename: String
let followers_list: [String:List]
let following_list: [String:List]
let mutual_list: [String:List]
let request_counter: String
let dream_destination_list: List?
let hidden_content_list: List?
let email: String
let username: String?
let password: String?
let salt: String
let social_media_auth: String?
let social_media_id: String?
let date_created: String
let last_seen: String
let is_suspended: String?
let is_notified: String?
let approve_token: String
let device_token: String?
let language_id: String?
let language_machine_name: String?
let language_label: String?
let active: String
}

松散蛇案例并使用CodingKeys来遵循Swift命名约定或使用具有您关心的值的公共结构(您不必对整个JSON有效负载进行建模)使用私有结构对JSON进行建模并使用自定义init(from decoder: Decoder) using this answer设置值。