【问题标题】:swift - Decoding JSON response (post comments) from Reddit APIswift - 从 Reddit API 解码 JSON 响应(发表评论)
【发布时间】:2021-03-11 02:31:33
【问题描述】:

我从 Reddit API(针对特定 subreddit 的一篇帖子)以 JSON 格式获取 reddit 帖子 cmets,然后通过 Structs 解析 JSON。当我尝试输出解码后的 cmets 时出现错误:

错误解码 Json cmets - typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription: “应解码 Dictionary 但找到一个数组 而是。”,基础错误:无))

也许我在结构体中遗漏了某些内容,或者在 Repository getComments 方法中遗漏了不匹配的类型。请指教。

enum RequestURL {
    
    case top(sub: String, limit: Int)
    case postAt(sub: String, id: String)
    
    var url: String {
        switch self {
        case .top(let sub, let limit):
            return "https://www.reddit.com/r/\(sub)/top.json?limit=\(limit)"
        case .postAt(let sub, let id):
            return "https://www.reddit.com/r/\(sub)/comments/\(id).json"
        }
    }
}

class HTTPRequester {
        
        init() {}
        
        func getData (url: RequestURL, completion: @escaping(Data?) -> Void) {
            
            guard let url = URL(string: url.url) else {
                print("Error: Request URL is nil!")
                completion(nil)
                return
            }
            
            URLSession.shared.dataTask(with: url) {data,_,error in
                guard let jsonData = data else {
                    print(error ?? "Error")
                    completion(nil)
                    return
                }
                completion(jsonData)
            }.resume()
        }
    }


class Service {
    
    init() {}
    
    func decodeJSONComments(url: RequestURL, completion: (@escaping (_ data: CommentListing?) -> Void)) {
        
        HTTPRequester().getData(url: url) { jsonData in
            do {
                let postsResponse = try JSONDecoder().decode(CommentListing.self, from: jsonData!)
                print(postsResponse)
                completion(postsResponse)
            } catch {
                print("Error decoding Json comments - \(error)")
                completion(nil)
            }
        }
    }
}

class Repository {
    
    init() {}
    
    func getComments(sub: String, postId: String, completion: (@escaping ([RedditComment]) -> Void)) {
        Service().decodeJSONComments(url: RequestURL.postAt(sub: sub, id: postId)) { (comments: CommentListing?) in
            
            var commentsList = [CommentData]()
            commentsList = (comments?.data.children) ?? []
            
            let mappedComs = commentsList.map { (comment) -> RedditComment in
                
                return RedditComment(
                    id: comment.data.id,
                    author: comment.data.author,
                    score: comment.data.score,
                    body: comment.data.body)
            }
            completion(mappedComs)
        }
    }
}

class UseCase {
    
    func createComments(sub: String, postId: String, completion: (@escaping (_ data: [RedditComment]) -> Void)) {
        Repository().getComments(sub: sub, postId: postId) { (comments: [RedditComment]) in
            completion(comments)
        }
    }
}

UseCase().createComments(sub: "ios", postId: "4s4adt") { comments in
   print(comments)
}

JSON 结构

【问题讨论】:

    标签: ios json swift api reddit


    【解决方案1】:

    你提到你有以下错误:

    typeMismatch(Swift.Dictionary<String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))
    

    让我们解构它:

    您可以从中阅读以下两点有用的信息:

    首先,debugDescription:应解码 Dictionary 但找到了一个数组。

    这意味着您正在尝试解码字典,但 JSON 包含一个数组。请注意,您标记为 Codable 的大多数普通类型都将编码为字典。

    第二个,codingPath,在你的例子中是一个空数组 ([]),这意味着这个问题就在你试图解码的根类型上。

    现在让我们看看您发布的 Postman 回复。在第 1 行,您可以看到最外面的容器(第 1 行)是一个数组。

    但是当你解码时,你正在解码一个CommentListing,它使用一个键控容器(字典)。

    因此,要解决此问题,您必须解码 CommentListings 的数组。

    let postsResponse = try JSONDecoder().decode([CommentListing].self, from: jsonData!)
    

    【讨论】:

    • 感谢您的回答和清晰的解释!!
    【解决方案2】:

    尝试将您的响应解码为CommentListing 的数组,例如:

    do {
        let postsResponse = try JSONDecoder().decode([CommentListing].self, from: jsonData!)
        print(postsResponse)
        completion(postsResponse)
    } catch {
        print("Error decoding Json comments - \(error)")
        completion(nil)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      相关资源
      最近更新 更多