1

这是一个与 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().decode,我就会得到上述格式的模型对象。但是,Author 类中的 links 属性是作为字典获取的。现在要访问 self 字段的值,我需要大致执行以下操作:

let selfLink = author.links["self"]
let href = selfLink[0].href 

有没有更好的方法来为结构建模以避免这种情况?

4

3 回答 3

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

于 2018-05-14T00:05:26.407 回答
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
于 2018-05-13T19:36:14.093 回答
1

在您的 JSON 中不太常见或至少命名不当的一件事是,该links属性实际上不是一个集合,而是一个集合的包装器对象self。这就是为什么我会忠于数据并将属性映射到links名称linksWrapper(对象)和(集合)的原因。selflinks

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 结构本身中解决此问题,请改为这样做。

于 2018-05-14T08:58:28.997 回答