【问题标题】:How to debug JSONDecoder when no errors show?没有错误显示时如何调试 JSONDecoder?
【发布时间】:2021-06-06 23:09:33
【问题描述】:

我正在构建一个 Swift 应用程序并在 Xcode Playground 中进行测试。调用 NYTimes Search API 并尝试将其响应存储在结构中。代码执行干净,没有出现错误(我正在使用 do、try、catch),但我无法从结果对象中打印任何属性 (print(json.status))。

我的预感是这条线有些可疑,但我不确定是什么,因为从 catch 语句中没有打印错误

let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in

形成 URL 端点以进行 API 调用:

func APICall() {
        
        let APIKey = "MY_API_KEY_GOES_HERE_BUT_IT'S_A_SECRET"
        let searchTerm = "A Super Bowl Sideshow: See the Ageless Man!"
        
        // Remove the spaces and convert them to percents
        guard let encodedSearchTerm = searchTerm.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) 
           else {
              print("Error encoding search term in URL")
              return
        }
    
        let url = "https://api.nytimes.com/svc/search/v2/articlesearch.json?q=" + encodedSearchTerm + "&api-key=" + APIKey

        getData(from: url)
}

数据任务:

func getData(from url: String) {
    
    //I believe something is wrong with the following line but I'm not sure what it is
    let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { data, response, error in
        
        guard let data = data, error == nil else {
            print("Error loading data")
            return
        }
        
        var result: NYTSearchResponse?
        
        do {
            
            result = try JSONDecoder().decode(NYTSearchResponse.self, from: data)
            
        } catch {
            print(error)
        }
        
        guard let json = result else {
            print("Error assigning result to json")
            return
        }
        
        //Try to print these from the resulting object but these commands do not print
        print(json.status)
        print(json.response.docs[0].abstract)
    })
    
    task.resume()
}

我的 NYTSearchResponse 结构,它反映了 NYT API JSON 响应。这很复杂,但我将 json 响应粘贴到 https://app.quicktype.io/ 以构建结构。

// MARK: - Welcome
struct NYTSearchResponse: Codable {
    let status, copyright: String
    let response: Response
}

// MARK: - Response
struct Response: Codable {
    let docs: [Doc]
    let meta: Meta
}

// MARK: - Doc
struct Doc: Codable {
    let abstract: String
    let webURL: String
    let snippet, leadParagraph, printSection, printPage: String
    let source: String
    let multimedia: [Multimedia]
    let headline: Headline
    let keywords: [Keyword]
    let pubDate: Date
    let documentType, newsDesk, sectionName, subsectionName: String
    let byline: Byline
    let typeOfMaterial, id: String
    let wordCount: Int
    let uri: String

    enum CodingKeys: String, CodingKey {
        case abstract
        case webURL = "web_url"
        case snippet
        case leadParagraph = "lead_paragraph"
        case printSection = "print_section"
        case printPage = "print_page"
        case source, multimedia, headline, keywords
        case pubDate = "pub_date"
        case documentType = "document_type"
        case newsDesk = "news_desk"
        case sectionName = "section_name"
        case subsectionName = "subsection_name"
        case byline
        case typeOfMaterial = "type_of_material"
        case id = "_id"
        case wordCount = "word_count"
        case uri
    }
}

// MARK: - Byline
struct Byline: Codable {
    let original: String
    let person: [Person]
    let organization: String?
}

// MARK: - Person
struct Person: Codable {
    let firstname: String
    let middlename: String?
    let lastname: String
    let qualifier, title: String?
    let role, organization: String
    let rank: Int
}

// MARK: - Headline
struct Headline: Codable {
    let main: String
    let kicker, contentKicker: String?
    let printHeadline: String
    let name, seo, sub: String?

    enum CodingKeys: String, CodingKey {
        case main, kicker
        case contentKicker = "content_kicker"
        case printHeadline = "print_headline"
        case name, seo, sub
    }
}

// MARK: - Keyword
struct Keyword: Codable {
    let name, value: String
    let rank: Int
    let major: String
}

// MARK: - Multimedia
struct Multimedia: Codable {
    let rank: Int
    let subtype: String
    let caption, credit: String?
    let type, url: String
    let height, width: Int
    let legacy: Legacy
    let subType, cropName: String

    enum CodingKeys: String, CodingKey {
        case rank, subtype, caption, credit, type, url, height, width, legacy, subType
        case cropName = "crop_name"
    }
}

// MARK: - Legacy
struct Legacy: Codable {
    let xlarge: String?
    let xlargewidth, xlargeheight: Int?
}

// MARK: - Meta
struct Meta: Codable {
    let hits, offset, time: Int
}

【问题讨论】:

  • 那么实际打印的是什么?
  • 另外你怎么知道你没有打印空字符串?为什么不打印json 本身并实际看看你有什么?甚至使用调试器?
  • @matt 没有打印!刚刚尝试打印(json)。
  • 我也在 Xcode 中使用游乐场。当我在 APICall() 中 print(url) 时,url 字符串显示在屏幕右侧,但 getData() 中的 print(json) 并没有在右侧列显示任何预览
  • 尝试使用非游乐场。游乐场不适合这种事情。

标签: ios json swift api jsondecoder


【解决方案1】:

我将代码移出操场,它可以工作。

【讨论】:

  • 麻烦的是,原来的问题从来没有提到操场。
  • 抱歉,我对编码很陌生,对 Xcode 和 StackOverflow 也很陌生。一切都会变得更好!
  • 好的,但我的建议是:让我们编辑问题,让游乐场成为其中的一部分。这将使这个问答对人们有用。否则这只是你个人的博客,讲述你在编程中的个人冒险经历,这不是对 Stack Overflow 的正确使用。
  • 我明白了。进行了编辑以在原始问题中提及游乐场的使用。
  • 是的,现在我们正在做饭。 :) 也许游乐场可以通过延长寿命来工作;这里的问题是您的代码是异步的,因此操场在我们到达代码末尾之前就停止了。但实际上最好在一个真正的项目中开发,在那里您可以获得调试器和其他形式的理智的好处。游乐场只是为了玩耍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多