Swift 4 JSON解码根数组

时间:2018-03-20 14:38:23

标签: ios json swift4 codable decodable

我在使用Swift 4解码功能解码JSON响应方面遇到了问题。 我有主要构造,它有一个内部构造var hr_employees:[Employee]? = []。问题是JSON没有映射'var hr_employees:[Employee]? = []。

我得到三个根值response_status,access_level,session_token的正确值。

////////////结构代码////////////////////////

struct EmployeeData: Codable {
     var response_status:Int=0
     var access_level:Int=0
     var session_token:String=""
     var hr_employees: [Employee]? = []
}

private enum CodingKeys: String, CodingKey {
        case response_status="response_status"
        case access_level="access_level"
        case session_token="session_token"
        case hr_employees="hr_employees"
    }

    init() {

    }



init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            response_status = try values.decode(Int.self, forKey: .response_status)
            do{
                session_token = try values.decode(String.self, forKey: .session_token)
            }catch {
                print( "No value associated with key title (\"session_token\").")
            }
            do{
                access_level = try values.decode(Int.self, forKey: .access_level)
            }
            catch {
                print( "No value associated with key access_level ")
            }
        }

/////////////////内部结构///////////////////////

  struct Employee: Codable {
        var userId:Int=0
        var nameFirst:String=""
        var nameLast:String=""
        var position:String=""
        var company:String=""
        var supervisor:String=""
        var assistant:String=""
        var phone:String=""
        var email:String=""
        var address:String=""
        var gender:String=""
        var age:Int=0
        var nationality:String=""
        var firstLanguage:String=""
        var inFieldOfView:String = "0"
        var photo:String="user-default"
        var status:String="3"
    }

////////////以下是JSON //////////////////////

{
"response_status":1
,"access_level":2
,"hr_employees":[
{
"user_id":4226
,"name_last":"Sampe"
,"name_first":"Frederica"
,"position":"Systems Maint"
,"phone":"123456"
,"email":"omega@demo.mobile"
,"address":"00100 Helsinki 1"
,"age":67
,"company":"Omega Enterprise"
}
,{
"user_id":5656
,"name_last":"Aalto"
,"name_first":"Antero"
,"position":"Programming Methodology and Languages Researcher"
,"supervisor":"Mayo Georgia"
,"phone":"123456"
,"email":"omega@demo.mobile"
,"address":"00100 Finland "
,"age":51
,"company":"Omega Fire Related Equipment"
}
]
}

2 个答案:

答案 0 :(得分:1)

一个问题是JSON中的内容与您的Employee定义不匹配。例如,nameFirst不存在且name_first是。

另一个是您有init(from:)的自定义实现,它永远不会获取hr_employees值!

答案 1 :(得分:0)

您需要改进的一些事项:

  1. 可以改进Struct以利用Codable协议的自动化功能。
  2. 您需要了解为何使用CodingKeys枚举
    • 在您的情况下......也是最好的地方(提示:在Struct内部)
  3. 您需要知道哪些参数需要是可选的以及为什么
    • 这取决于你的json结构的课程
  4. 如果参数具有默认值,那么您需要遵循完整的不同过程;比如拥有自己的init(from:Decoder)
    • 你必须在某种程度上但并没有真正处理当前状态中的所有内容
  5. 根据您给定的JSON示例,您可以简单地执行以下操作 但是...... 请注意,这不是为了提供默认值。即如果json中缺少某个键,例如status,则status结构中的参数Employee将为nil,而不是默认值{{ 1}}。

    "3"
    struct EmployeeData: Codable {
        var responseStatus: Int
        var accessLevel: Int
    
        /*
         sessionToken is optional because as per your JSON
         it seems it not always available
         */
        var sessionToken: String?
    
        var hrEmployees: [Employee]
    
        /*
         CodingKeys is inside the struct
         It's used if the JSON key names are different than
         the ones you plan to use.
         i.e. JSON has keys in snake_case but we want camelCase
         */
        enum CodingKeys: String, CodingKey {
            case responseStatus = "response_status"
            case accessLevel = "access_level"
            case sessionToken = "session_token"
            case hrEmployees = "hr_employees"
        }
    }
    

    检查:

    struct Employee: Codable {
        var userId: Int
        var nameFirst: String
        var nameLast: String
        var position: String
        var company: String
        var supervisor: String?
        var assistant: String?
        var phone: String
        var email: String
        var address: String
        var gender: String?
        var age: Int
        var nationality: String?
        var firstLanguage: String?
        var inFieldOfView: String?
        var photo: String?
        var status: String?
    
        enum CodingKeys: String, CodingKey {
            case userId = "user_id"
            case nameFirst = "name_first"
            case nameLast = "name_last"
            case firstLanguage = "first_language"
            case inFieldOfView = "in_field_of_view"
    
            /*
             Keys names that are same in json as well as in your
             model need not have a raw string value
             but must be defined if it's to be encoded/decoded
             from the json else it can be omitted and a default
             value will be required which won't affect the encoding
             or decoding process
             */
            case position
            case company
            case supervisor
            case assistant
            case phone
            case email
            case address
            case gender
            case age
            case nationality
            case photo
            case status
        }
    }
    

    如果你想要do { let employeeData = try JSONDecoder().decode(EmployeeData.self, from: jsonAsData) print(employeeData) } catch { /* If it comes here then debug, it's most probably nil keys meaning you need more optional parameters in your struct */ print(error) } 中的默认值,而上面的例子对你来说是一个破坏者,那么请检查以下答案: