【问题标题】:Passing JSON result into a struct model将 JSON 结果传递给结构模型
【发布时间】:2019-03-21 15:44:33
【问题描述】:

我从 API 接收结果,我可以遍历结果。我的理解是我可以立即将值传递给模型。

Apple Developer article on struct models

我的问题是我没有正确执行并且收到 nil 值。也许有人可以看到我需要改变的地方。我正在使用 Swift 4.2

这是我的结构模型。

import Foundation

struct ProfileModel {

//MARK: Properties

var name: String
var email: String
var profileURL: String

//MARK: Initialization


}
extension ProfileModel{
  init?(json: [String:AnyObject]) {
    guard
        let name = json["name"] as? String,
        let email = json["email"] as? String,
        let profileURL = json["profileURL"] as? String
        else { return nil }

    self.name = name
    self.email = email
    self.profileURL = profileURL
  }
}

这是来自我的 urlConnection 的结果代码。如果我们想查看整个 swift 文件,请告诉我

//create dataTask using the session object to send data to the server
    let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in

        guard error == nil else {
            return
        }

        guard let data = data else {
            return
        }

        do {
            //create json object from data
            if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:AnyObject] {

                self.onSuccess(data: json)

            }
        } catch let error {
            print(error.localizedDescription)
        }
    })
    task.resume()

}


func onSuccess(data: [String:AnyObject]){
  print("onSuccess")

  let myProfile = ProfileModel(json: data)
  //myProfile is nil while unwrapping
  let title: String = myProfile!.name
  print(title)
}

我可以遍历字符串,因为我可以打印“数据”。我只是认为将所有内容放入 ProfileModel 并作为一个整体管理该对象会更简洁。

这个 json 是我比较简单的一个,这就是为什么我用它来回答这个问题。我也不记得了,但我不得不使用“[String:AnyObject]”来正确获取 json。这是直接从我的终端中提取的,这是在我的 JsonResponse 中传递的数据。 Xcode 的输出 json 在外面有 []。

{
'detail': 'VALID', 
‘name’: ‘Carson, 
'email': ‘carson.skjerdal@somethingelselabs.com', 
'pic_url': None
}

编辑:

所以我的问题解决了,最终转向 Codable 是关键。这是我为任何可能需要有效解决方案的人提供的固定代码。

URLSession.shared.dataTask(with: request as URLRequest) { (data, response
        , error) in
        guard let data = data else { return }
        do {
            let decoder = JSONDecoder()
            let gitData = try decoder.decode(ProfileModel.self, from: data)
            print(gitData.name)
            self.onSuccess(data: gitData)

        } catch let err {
            print("Err", err)
        }
        }.resume()

}

func onSuccess(data: ProfileModel){
  print("onSuccess")

  print(data.email)

}

我的 Codable 结构 - 稍微简化

import Foundation

struct ProfileModel: 可编码 { 让详细信息,姓名,电子邮件:字符串

private enum CodingKeys: String, CodingKey {
    case detail, email
    case name = "firstname"
    //case picUrl = "pic_url"
}

}

【问题讨论】:

  • 你的初始化失败了。好吧,它失败了。
  • 比起查看整个 swift 文件,查看 JSON 会更有帮助。并且提到的Apple文章没有建议AnyObjectmutableContainers。顺便说一句,这篇文章已经过时了,支持Codable 协议
  • init?(json:): 失败。里面有一个guard condition1, condition2, condition 3 else { return nil }。可能想检查哪一个条件失败,以及原因。
  • 添加了我的 json,即使一个失败,我的 init 也会失败吗?我刚刚修复了一个拼写错误,所以我会运行它。编辑:我把所有的拼写都修好了,所以应该没问题。 @vadin 我没有意识到它已经过时了,我认为这是最新的。
  • 这不是有效的 JSON。所有字符串,但用双引号括起来,例如"detail": "VALID"。并且 JSON 与您的模型不匹配,没有 profileURL 键,在这种情况下初始化程序失败。

标签: ios json swift xcode struct


【解决方案1】:

在引入“可编码”之后,我总是使用它。 你可以把你的 JSON 解析到 QuickType.io,你会得到一个 Struct 来确认 codadable

// To parse the JSON, add this file to your project and do:
//
//   let aPIResponse = try? newJSONDecoder().decode(APIResponse.self, from: jsonData)

import Foundation

struct APIResponse: Codable {
    let detail, name, email, picUrl: String

    enum CodingKeys: String, CodingKey {
        case detail, name, email
        case picUrl = "pic_url"
    }
}

【讨论】:

  • 太棒了,我不会投票正确(还),但这对我来说是一大步。听起来 Codable 是解决这个问题的方法。
  • 我将此标记为正确,因为这是一大步,我会将正确的代码发布给阅读我帖子的任何人。
猜你喜欢
  • 1970-01-01
  • 2016-01-30
  • 2023-03-15
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
相关资源
最近更新 更多