【问题标题】:Swift 4 JSON Decode Root ArraySwift 4 JSON 解码根数组
【发布时间】:2018-03-20 14:38:23
【问题描述】:

我在使用 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"
}
]
}

【问题讨论】:

    标签: ios json swift4 codable decodable


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      有很多事情需要你改进:

      1. 您的Structs 可以改进以利用Codable 协议的自动化功能。
      2. 您需要了解为什么要使用CodingKeys 枚举
        • 在你的情况下......也是最好的地方(提示:在Struct 本身内)
      3. 您需要知道哪些参数需要是可选的以及为什么
        • 这当然取决于你的 json 结构
      4. 如果参数要具有默认值,那么您需要遵循一个完全不同的过程;就像拥有自己的init(from:Decoder)
        • 您在一定程度上需要,但并不能真正处理当前状态下的所有内容

      根据您给定的 JSON 示例,您可以简单地执行以下操作。
      但是...请注意,这并非旨在提供默认值。即,如果 json 中缺少某个键,例如 status,那么 Employee 结构中的参数 status 将是 nil,而不是默认值 "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)
      }
      

      如果你想在你的Struct 中使用默认值,而上面的例子对你来说是一个破坏者,那么请检查以下答案:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        相关资源
        最近更新 更多