Swift 4-将类结构的JSON响应嵌套到TableViewCell中

时间:2018-07-16 05:35:43

标签: ios json swift swift4

我具有以下结构来帮助从JSON Web API返回数据:

// To parse the JSON, add this file to your project and do:
//
//   let story = try? JSONDecoder().decode(Story.self, from: jsonData)

import Foundation

typealias Story = [StoryElement]

struct StoryElement: Codable {
    let id: Int
    let url: String
    let storyPublic, featured: Bool
    let added, modified: String
    let itemType: ItemType
    let collection: JSONNull?
    let owner: Owner
    let files: Files
    let tags: [ItemType]
    let elementTexts: [ElementText]
    let extendedResources: ExtendedResources

    enum CodingKeys: String, CodingKey {
        case id, url
        case storyPublic = "public"
        case featured, added, modified
        case itemType = "item_type"
        case collection, owner, files, tags
        case elementTexts = "element_texts"
        case extendedResources = "extended_resources"
    }
}

struct ElementText: Codable {
    let html: Bool
    let text: String
    let elementSet: ElementSet
    let element: Element

    enum CodingKeys: String, CodingKey {
        case html, text
        case elementSet = "element_set"
        case element
    }
}

struct Element: Codable {
    let id: Int
    let url, name: String
    let resource: ElementResource
}

enum ElementResource: String, Codable {
    case elements = "elements"
}

struct ElementSet: Codable {
    let id: Int
    let url: URL
    let name: Name
    let resource: ElementSetResource
}

enum Name: String, Codable {
    case dublinCore = "Dublin Core"
    case itemTypeMetadata = "Item Type Metadata"
}

enum ElementSetResource: String, Codable {
    case elementSets = "element_sets"
}

enum URL: String, Codable {
    case httpWWWRalstoncemeteryCOMGreeleyAPIElementSets1 = "http://www.ralstoncemetery.com/greeley/api/element_sets/1"
    case httpWWWRalstoncemeteryCOMGreeleyAPIElementSets3 = "http://www.ralstoncemetery.com/greeley/api/element_sets/3"
}

struct ExtendedResources: Codable {
    let exhibitPages: Files
    let geolocations: Owner

    enum CodingKeys: String, CodingKey {
        case exhibitPages = "exhibit_pages"
        case geolocations
    }
}

struct Files: Codable {
    let count: Int
    let url, resource: String
}

struct Owner: Codable {
    let id: Int
    let url, resource: String
}

struct ItemType: Codable {
    let id: Int
    let url, name, resource: String
}

// MARK: Encode/decode helpers

class JSONNull: Codable {
    public init() {}

    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if !container.decodeNil() {
            throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull"))
        }
    }

    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encodeNil()
    }
}

您可以在此处查看正在使用的JSON输出以及原始结构:https://app.quicktype.io?share=oAMNjooSzgpraWpf1KIj(仅供参考)。

(我相信)数据已成功返回并正确解析,唯一的问题是我自己不那么熟悉(我正在尝试学习更多知识)。

所以我有一个TableViewController,其中有一个单元格,其中带有以下代码:

struct StoryCellViewModel {
    let id: Int
    let url: String
    let storyPublic, featured: Bool
    let added, modified: String
}

在viewDidLoad()下的实际TableViewController中,我具有脚本的这一部分:

 print(story)
                self.cellViewModels = story.map{
                    StoryCellViewModel(id: $0.id, url: $0.url, storyPublic: $0.storyPublic, featured: $0.featured, added: $0.added, modified: $0.modified)
                }

还有一点点,我有:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "StoryCell", for: indexPath)

    let cellViewModel = cellViewModels[indexPath.row]
    cell.textLabel?.text = String(cellViewModel.id)
    cell.detailTextLabel?.text = cellViewModel.modified


    return cell
}

我将使所有这些工作,id和修改(都被用作确保连接和打印正常工作的测试)都可以了,但是我的问题出在这里:

如果我们回到结构,则有以下部分:

struct ElementText: Codable {
    let html: Bool
    let text: String
    let elementSet: ElementSet
    let element: Element

    enum CodingKeys: String, CodingKey {
        case html, text
        case elementSet = "element_set"
        case element
    }
}

参考示例JSON的以下部分:

"element_texts": [
      {
        "html": false,
        "text": "Woehler and Force Farm Equipment Building",
        "element_set": {
          "id": 1,
          "url": "http://www.ralstoncemetery.com/greeley/api/element_sets/1",
          "name": "Dublin Core",
          "resource": "element_sets"
        },
        "element": {
          "id": 50,
          "url": "http://www.ralstoncemetery.com/greeley/api/elements/50",
          "name": "Title",
          "resource": "elements"
        }
      },
      {
        "html": false,
        "text": "Woehler and Force Farm Equipment",
        "element_set": {
          "id": 1,
          "url": "http://www.ralstoncemetery.com/greeley/api/element_sets/1",
          "name": "Dublin Core",
          "resource": "element_sets"
        },
        "element": {
          "id": 39,
          "url": "http://www.ralstoncemetery.com/greeley/api/elements/39",
          "name": "Creator",
          "resource": "elements"
        }
      },
      {
        "html": false,
        "text": "Street view of the front exterior of Woehler and Force Farm Equipment. Several automobiles are visible through the windows of the store. The alley along the side of the building is also visible. There are several signs along the front of the building reading, 'Farm Equipment,' 'Kaiser Frazer W&F,' and 'Woehler & Force.'; Verso There is a sticker with typed black ink reading, 'Woehler & Force 1316-22 8th Ave. - Greeley, CO 1947. Orig. env. says Liberty Trucker Parts Co./ 690 Lincoln St./F.V. Altwater/POB 1889/Denver, Colo.'",
        "element_set": {
          "id": 3,
          "url": "http://www.ralstoncemetery.com/greeley/api/element_sets/3",
          "name": "Item Type Metadata",
          "resource": "element_sets"
        },
        "element": {
          "id": 54,
          "url": "http://www.ralstoncemetery.com/greeley/api/elements/54",
          "name": "Story",
          "resource": "elements"
        }
      }
    ],

**所以我的问题是:** element_texts中的第一个(text中设置了“ Woehler and Force Farm Equipment Building”的人)字段)?

如果需要任何进一步的说明,我很乐意输入。或者,如果有人有任何资源可以进行此嵌套级别,我将不胜感激。谢谢-

3 个答案:

答案 0 :(得分:1)

  • storyStoryElement的数组(为什么不是stories?)
  • elementTexts中属性StoryElement的类型是ElementText的数组

因此,基本上,您需要两个循环来迭代storyelementTexts

for aStory in story {
    for elementText in aStory.elementTexts {
        print(elementText.text)
    }
}

答案 1 :(得分:0)

首先在“ CellForRowat”调用中,让cell = dequeueReusableCellWithIdentifier:@“ cell” for IndexPath:indexPath等。

然后将文本放置在cell.text中

答案 2 :(得分:0)

创建一个像这样的数组。 var AllTexts = [String]()

您可以通过JsonDecode / JSONSerialization等多种方式来获取JSON数据,我正在使用JSONSerialization。提取数据后,我将文本值附加到数组中。

 do {
            let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
            let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) as! [String: Any]
            for (key,value) in jsonResult {
                 print(key)
                  if let result2:[[String:Any]] = value as? [[String:Any]]{
                     for dict in result2 {

                        for (key,value) in dict {
                              if key == "text" {
                                 self.AllTexts.append(value as! String)
                             }
                        }
                    }
                  }
            }
            print(self.AllTexts)
        } catch {
            // handle error
            print(error)
        }