这是与swift上的JSONDecoder可编码功能相关的模型设计相关问题。
我有以下JSON:
"author": {
"name": "abc",
"emailAddress": "abc@xyz.com",
"id": 8665,
"displayName": "A B C",
"active": true,
"slug": "abc",
"type": "NORMAL",
"links": {
"self": [
{
"href": "some_href"
}
]
}
}
我正在尝试使用新的swift 4 Codeable功能解码它。
因此我按如下方式创建了我的结构:
struct Author: Codeable {
let name: String,
let emailAddress: String,
let id: String,
let displayName: String,
let active: String,
let type: String,
let links: [String: [Link]]
}
struct Link: Codeable {
let href: String
}
一旦我在这个json上运行JSONDecoder()。解码,我就得到了上述格式的模型对象。但是,Author类中的links属性是作为字典获取的。现在要访问自我字段的值,我需要粗略地做如下:
let selfLink = author.links["self"]
let href = selfLink[0].href
有没有更好的方法来对结构进行建模,以便可以避免这种情况?
答案 0 :(得分:1)
是的,您可以通过再添加一个变量来实现:
struct Author: Codable {
let name: String
let emailAddress: String
let id: String
let displayName: String
let active: String
let type: String
let links: [String: [Link]]
var linkArr: [Link]? {
return links["self"]
}
}
直接得到:
author.linkArr[0].href
答案 1 :(得分:1)
如果您确定每位作者总是至少有1 href
,则可以添加计算属性:
struct Author: Codable {
let name: String
let emailAddress: String
let id: String
let displayName: String
let active: String
let type: String
let links: [String: [Link]]
var href: String {
return links["self"]!.first!.href
}
}
您也可以通过声明links
从外部无法访问private
。
答案 2 :(得分:1)
在JSON中不常见或至少不恰当地命名的一件事是links
属性实际上不是集合,而是集合self
的包装器对象。这就是为什么我会坚持数据是什么,并将links
属性映射到名称linksWrapper
(对象)和self
到links
(集合)。
struct Author: Codable {
let name: String
let emailAddress: String
let id: Int
let displayName: String
let active: Bool
let slug: String
let type: String
let linksWrapper: LinksWrapper
enum CodingKeys: String, CodingKey {
case name, emailAddress, id, displayName, active, slug, type
case linksWrapper = "links"
}
}
struct LinksWrapper: Codable {
let links: [Link]
enum CodingKeys: String, CodingKey {
case links = "self"
}
}
struct Link: Codable {
let href: String
}
然后,您可以按照JSON模型建议的相同层次顺序访问链接,但名称更有意义:
let myLinks = author.linksWrapper.links.first
但为方便起见,您可以向readonly
添加links
Author
媒体资源:
var links: [Link] {
return linksWrapper.links
}
然后您可以直接访问链接:
let myLinks = author.links
但是,如果您有机会在JSON结构中修复此问题,那么请执行此操作。