json - 在 Swift 4 中序列化 JSON - 确定数据类型的问题

标签 json swift codable

我正在从在线 API 中获取一些 JSON,并将结果放入数组中以备将来使用。到目前为止,所有数据都很好(只是字符串数组),但我不知道如何处理其中一个结果。

This is the JSON (有人建议我使用 https://jsonlint.com 使其可读并且非常有用)

这是获取 JSON 的函数:

func getJSON(completionHandler: @escaping (Bool) -> ()) {
    let jsonUrlString = "https://api.nytimes.com/svc/topstories/v1/business.json?api-key=f4bf2ee721031a344b84b0449cfdb589:1:73741808"
    guard let url = URL(string: jsonUrlString) else {return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data, err == nil else {
            print(err!)
            return
        }

        do {
            let response = try
                JSONDecoder().decode(TopStoriesResponse.self, from: data)

            // Pass results into arrays (title, abstract, url, image)
            for result in response.results {
                let headlines = result.title
                let abstracts = result.abstract
                let url = result.url

                self.headlines.append(headlines)
                self.abstracts.append(abstracts)
                self.urls.append(url)
            }

            let imageResponse = try
                JSONDecoder().decode(Story.self, from: data)
            for imageResults in imageResponse.multimedia {
                let images = imageResults.url
                self.images.append(images)
            }

            completionHandler(true)


        } catch let jsonErr {
            print("Error serializing JSON", jsonErr)
        }
    }.resume()
}

这些是用于序列化 JSON 的结构:

struct TopStoriesResponse: Decodable {
    let status: String
    let results: [Story]
}

struct Story: Decodable {
    let title: String
    let abstract: String
    let url: String
    let multimedia: [Multimedia]
}

struct Multimedia: Codable {
    let url: String
    let type: String
}

我将结果组织到这些数组中:

var headlines = [String]()
var abstracts = [String]()
var urls = [String]()
var images = [String]()

然后我调用了 viewDidLoad 中的函数

getJSON { (true) in
    print("Success")
    print("\n\nHeadlines: \(self.headlines)\n\nAbstracts: \(self.abstracts)\n\nURLS: \(self.urls)\n\nImages: \(self.images)")
}

正如您在 getJSON 函数中所见,我尝试使用

let imageResponse = try JSONDecoder().decode(Story.self, from: data)
for imageResults in imageResponse.multimedia {
    let images = imageResults.url
    self.images.append(images)
}

但是我得到了错误

CodingKeys(stringValue: "multimedia", intValue: nil)], debugDescription: "Expected to decode Array but found a string/data instead.", underlyingError: nil))

我很困惑,因为它说它期待一个数组,但却找到了一个字符串——图像不是数组吗,就像 headlinesabstracts 等?

最佳答案

问题在于 multimediaMultimedia 对象的数组或空的 String。您需要为 Story 编写自定义初始化程序来处理它。

struct Story: Decodable {
    let title: String
    let abstract: String
    let url: String
    let multimedia: [Multimedia]

    private enum CodingKeys: String, CodingKey {
        case title
        case abstract
        case url
        case multimedia
    }

    init(from decoder:Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        title = try container.decode(String.self, forKey: .title)
        abstract = try container.decode(String.self, forKey: .abstract)
        url = try container.decode(String.self, forKey: .url)
        multimedia = (try? container.decode([Multimedia].self, forKey: .multimedia)) ?? []
    }
}

关于json - 在 Swift 4 中序列化 JSON - 确定数据类型的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52876535/

相关文章:

javascript - JSON 解析的别名字段

c# - 在默认构造函数中初始化的 JSON.Net 集合未被反序列化的 JSON 覆盖

html - JSON - 从 YouTube 播放列表中获取超过 25 个视频

ios - 如何向从 nib 文件加载的 subview 添加约束?

ios - 解析 PFUser 是否下载所有用户对象列内容?

json - 使用具有多个 key 的 Decodable 协议(protocol)

json - Swift,当 key 未知/动态时,如何使用 Decodable 和 Codable 解析/解码 JSON

javascript - Json日期格式转换减去1天

swift - 从纵向移动到横向时如何修复 UIcollectionView 中的项目宽度?

json - 解码嵌套对象swift4 Codable