Swift JSONDecoder обрабатывает словарь массива словаря

Это вопрос, связанный с дизайном модели, связанный с кодируемой функциональностью JSONDecoder на swift.

У меня есть следующий JSON:

"author": {
    "name": "abc",
    "emailAddress": "[email protected]",
    "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
} 

После запуска JSONDecoder (). Decode на этом json я получаю объекты модели в указанном выше формате. Однако свойство ссылок в классе Author получается в виде словаря. А теперь, чтобы получить доступ к значению поля self, мне нужно сделать примерно следующее:

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

Есть ли лучший способ смоделировать структуру, чтобы этого можно было избежать?


person Vibin B. Nair    schedule 13.05.2018    source источник
comment
Спасибо, @ code-different попробую это сделать.   -  person Vibin B. Nair    schedule 14.05.2018
comment
Спасибо @ jogendar-choudhary. Попробую этот подход.   -  person Vibin B. Nair    schedule 14.05.2018


Ответы (3)


Да, вы можете сделать это, добавив еще одну такую ​​переменную:

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
person Jogendar Choudhary    schedule 13.05.2018

Если вы уверены, что у каждого автора всегда есть хотя бы 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.

person Code Different    schedule 14.05.2018

Одна вещь, которая не очень обычна или, по крайней мере, неправильно названа в вашем 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, сделайте это вместо этого.

person Au Ris    schedule 14.05.2018