【问题标题】:Codable: Process one key manually可编码:手动处理一键
【发布时间】:2019-04-01 04:45:27
【问题描述】:

我从 API 获取 JSON,并且大部分密钥都是开箱即用的。

示例 API 响应:

[
  { "href":"http:\/\/audiomachine.com\/",
    "description":"Audiomachine",
    "extended":"Music for videos",
    "shared":"yes",
    "toread":"no",
    "tags":"creative video music"
  },
  { "href": "https:\/\/www.root.cz\/clanky\/nekricte-na-disky-zvuk-i-ultrazvuk-je-muze-poskodit-nebo-zmast-cidla\/",
    "description":"Nek\u0159i\u010dte na disky: zvuk i\u00a0ultrazvuk je m\u016f\u017ee po\u0161kodit nebo zm\u00e1st \u010didla - Root.cz",
    "extended":"Added by Chrome Pinboard Extension",
    "shared":"yes",
    "toread":"no",
    "tags":"root.cz ril hardware webdev"
  },
  { "href": "https:\/\/www.premiumbeat.com\/blog\/10-apple-motion-tutorials-every-motion-designer-watch\/",
    "description":"10 Apple Motion Tutorials Every Motion Designer Should Watch",
    "extended":"For people used to working with FCPX, sometimes learning Apple Motion can be much easier than learning After Effects. While the two programs are different, there\u2019s certainly a lot of overlap in terms of functionality and creative potential. The following ten Apple Motion tutorials are great examples of just that.\r\n\r\nWhether you are someone new to Apple Motion or a seasoned veteran looking to up your skills, here are ten must watch Apple Motion tutorials.",
    "shared":"yes",
    "toread":"no",
    "tags":"apple apple_motion video creative effects"
  }
]

我将每个项目存储在以下结构中。

struct Link: Codable {
    let href: URL
    let description: String
    var tags: String
}

然后用类似的东西解码

URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
    guard let data = data, error == nil else { return }

    do {
        let decoder = JSONDecoder()
        let decodedData = try decoder.decode([Link].self, from: data)

从 API 数据中,我使用 hrefdescriptiontags标签 有点麻烦,因为我想在代码中将它用作字符串数组,但在 JSON 中它被检索为包含所有用空格分隔的标签的字符串。由于这是我的第一个项目,我用来学习iOS开发,我几乎不知道如何解决这个问题。

我可以通过谷歌搜索计算属性来接近,所以它可能类似于

struct Link: Codable {
    let href: URL
    let description: String
    var tags: String {
        return tagsFromServer.components(separatedBy: " ")
    }
}

,但我对这个解决方案有两个问题。

  1. 我有强烈的感觉,每次代码访问.tags时都会调用这个闭包。我宁愿在 JSON 检索时执行一次,然后再读取它的产品。
  2. 我完全不知道如何将“我从服务器获得的原始标签”/tagsFromServer 传递给闭包。

如果能填补我在术语方面的空白,或者提供有关此主题的精彩视频教程,我将不胜感激。

【问题讨论】:

  • 您能否提及您从相关服务器收到的示例响应?
  • @Sateesh 添加到我的问题中。 Ty 指出它丢失了????????

标签: ios json swift codable


【解决方案1】:

我建议编写一个自定义初始化器,将tags 解码为String 并拆分它:

struct Link: Decodable {
    let href: URL
    let description: String
    let tags: [String]

    private enum CodingKeys: String, CodingKey { case href, description, tags }

    init(from decoder: Decoder) throws {
       let container = try decoder.container(keyedBy: CodingKeys.self)
       href = try container(URL.self, forKey: .href)
       description = try container(String, forKey: .description)
       let tagsFromServer = try container(String.self, forKey: .tags)
       tags = tagsFromServer.components(separatedBy: " ")
    }  
}

您也可以使用计算属性,但必须添加CodingKeys

struct Link: Decodable {
    let href: URL
    let description: String
    let tagsFromServer : String

    private enum CodingKeys: String, CodingKey { case href, description, tagsFromServer = "tags" }

    var tags: [String] {
        return tagsFromServer.components(separatedBy: " ")
    }
}

【讨论】:

  • 是的,我在网上遇到过这样的事情,但我不想为已经工作的键编写代码。有没有办法做你提到的事情,但只是为了标签?你写的可能有效,但它引入了我不需要并且我必须维护的代码。
  • 我用计算属性解决方案更新了答案。如果要将类型映射到具有不同类型的存储属性,则必须编写自定义初始化程序来解码 all 键。仅手动解码几个键是不可能的。
  • 这非常接近我的想象 ;) 难道不能做类似你的选择,但预先存储 tagsFromServer.components(separatedBy: " ") 吗?
  • 不,要么您免费获得所有内容,要么手动您必须解码所有键。
猜你喜欢
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多