代码之家  ›  专栏  ›  技术社区  ›  bcye

如何从可解码数组访问容器(Swift)

  •  0
  • bcye  · 技术社区  · 6 年前

    我已经试过了,但是找不到解决这个问题的方法:

    我从Google Books API得到了以下示例响应:

    let json = """
    {
        "items": [
            {
            "volumeInfo": {
                "title": "Harry Potter und der Stein der Weisen",
                "description": "Eigentlich hatte Harry geglaubt, er sei ein ganz normaler Junge. Zumindest bis zu seinem elften Geburtstag. Da erfährt er, dass er sich an der Schule für Hexerei und Zauberei einfinden soll. Und warum? Weil Harry ein Zauberer ist. Und so wird für Harry das erste Jahr in der Schule das spannendste, aufregendste und lustigste in seinem Leben. Er stürzt von einem Abenteuer in die nächste ungeheuerliche Geschichte, muss gegen Bestien, Mitschüler und Fabelwesen kämpfen. Da ist es gut, dass er schon Freunde gefunden hat, die ihm im Kampf gegen die dunklen Mächte zur Seite stehen."
            }
            }
        ]
    }
    """.data(using: .utf8)
    

    此响应永远不会返回多个项目。(指定为参数)因此可以安全地假设项只有一个成员/第一个成员是正确的成员。

    为了表示一本我创建的结构的书:

    struct Book: Decodable {
    
        let title: String
        let description: String?
    
        enum OuterOuterCodingKeys: CodingKey {
            case items
        }
    
        enum OuterCodingKeys: CodingKey {
            case volumeInfo
        }
    
        enum CodingKeys: String, CodingKey {
            case title
            case description
        }
    
        init(from decoder: Decoder) throws {
            let outerOuterContainer = try decoder.container(keyedBy: OuterOuterCodingKeys.self)
        }
    }
    

    现在我已经走了这么远。我现在需要以某种方式从volumeInfo中提取项,但不知道如何进入数组。

    谢谢你的帮助!

    1 回复  |  直到 6 年前
        1
  •  2
  •   rob mayoff    6 年前

    你说得对,但我们可以给你的外号起个更好的名字 CodingKey 枚举,并将其设为私有。

    import Foundation
    
    let jsonData = """
    {
        "items": [
            {
            "volumeInfo": {
                "title": "Harry Potter und der Stein der Weisen",
                "description": "Eigentlich hatte Harry geglaubt, er sei ein ganz normaler Junge. Zumindest bis zu seinem elften Geburtstag. Da erfährt er, dass er sich an der Schule für Hexerei und Zauberei einfinden soll. Und warum? Weil Harry ein Zauberer ist. Und so wird für Harry das erste Jahr in der Schule das spannendste, aufregendste und lustigste in seinem Leben. Er stürzt von einem Abenteuer in die nächste ungeheuerliche Geschichte, muss gegen Bestien, Mitschüler und Fabelwesen kämpfen. Da ist es gut, dass er schon Freunde gefunden hat, die ihm im Kampf gegen die dunklen Mächte zur Seite stehen."
            }
            }
        ]
    }
    """.data(using: .utf8)!
    
    struct Book: Decodable {
    
        let title: String
        let description: String?
    
        init(from decoder: Decoder) throws {
            let rootContainer = try decoder.container(keyedBy: RootContainerKeys.self)
            var itemsContainer = try rootContainer.nestedUnkeyedContainer(forKey: .items)
            let itemContainer = try itemsContainer.nestedContainer(keyedBy: ItemKeys.self)
            let myContainer = try itemContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .volumeInfo)
            self.title = try myContainer.decode(String.self, forKey: .title)
            self.description = try myContainer.decodeIfPresent(String.self, forKey: .description)
        }
    
        private enum CodingKeys: String, CodingKey {
            case title
            case description
        }
    
        private enum RootContainerKeys: CodingKey {
            case items
        }
    
        private enum ItemKeys: CodingKey {
            case volumeInfo
        }
    }
    
    let book = try? JSONDecoder().decode(Book.self, from: jsonData)
    print(book)