【问题标题】:How can I read the nested json data by using swift combine如何使用 swift combine 读取嵌套的 json 数据
【发布时间】:2020-03-10 16:47:34
【问题描述】:

我刚开始使用 combine swift 来处理数据请求和响应。

返回的 Json 数据是一个嵌套数据,我只需要它的一部分。 如:

{
"page": 1,
"data": [
{
"id": 1,
"title": "news-1",
"content": "content 1"
},
{
"id": 2,
"title": "news-2",
"content": "content 2"
},
{
"id": 3,
"title": "news-3",
"content": "content 3"
}
],
"time": 202021313,
"description" :"xxxx"
}

我需要使用data 数组。

获取以下函数:

    func fetchData() throws -> URLSession.DataTaskPublisher {
        let headers = [
            "Content-Type": "application/json",
            "cache-control": "no-cache",
        ]

        guard let url = URL(string: endpointStr ) else {
            throw APIError.invalidEndpoint
        }

        var request = URLRequest(url: url,
        cachePolicy: .useProtocolCachePolicy,
        timeoutInterval: 10.0)

        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        return session.dataTaskPublisher(for: request)
    }
        let publisher = try? fetchData()
        let decoder = JSONDecoder()
        let cancellable = publisher?
            .receive(on: DispatchQueue.main)
            .map {
                 $0.data
            }
            .decode(type: DataModel.self, decoder: decoder)
            .sink(receiveCompletion: { (completion) in
            switch completion {
            case .failure(let error):
                print("Error:")
                print(error)
            case .finished:
                print("DONE - get Publisher")
            }
        }, receiveValue: { data in
            print(data.title)
        })

它返回的数据是完整的json数据,有什么优雅的方法可以只获取数据数组并转换为[DataModel]数组并在receiveValue中处理数据。

我尝试编辑地图但没有成功:

            .map {
                if let dataString = String(data: $0.data, encoding: .utf8) {
                    let dataDic = APIService.convertToDictionary(text: dataString)
                    if let DataArray = dataDic?["data"] {
                        return listDataDic! 
                    }
                 return $0.data
                }

【问题讨论】:

    标签: json swift combine


    【解决方案1】:

    请澄清我是否误解了这个问题,但是如果您使用另一个模型来解码您的[DataModel],然后映射到解码后的[DataModel] 数组呢?

    这是一个单元测试示例。 Response 是将[DataModel] 数组解码为您可以使用的新模型。

    
    import XCTest
    import Combine
    
    let data = """
    {
      "page": 1,
      "data": [
        {
          "id": 1,
          "title": "news-1",
          "content": "content 1"
        },
        {
          "id": 2,
          "title": "news-2",
          "content": "content 2"
        },
        {
          "id": 3,
          "title": "news-3",
          "content": "content 3"
        }
      ],
      "time": 202021313,
      "description": "xxxx"
    }
    """.data(using: .utf8)!
    
    class Response: Codable {
        var data: [DataModel]
    }
    
    class DataModel: Codable {
        let id: Int
        let title: String
        let content: String
    }
    
    class Test: XCTestCase {
        func testDecodeDataModel() {
            let e = expectation(description: "finished expectation")
            let decoder = JSONDecoder()
            let cancellable = Just(data)
                .decode(type: Response.self, decoder: decoder)
                .map { $0.data }
                .sink(receiveCompletion: { (completion) in
                    // handle completion..
                }, receiveValue: { dataArray in
                    print(dataArray.count) // here you can work with your [DataModel] array
                    e.fulfill()
                })
            wait(for: [e], timeout: 1)
        }
    }
    

    【讨论】:

    • 它有效。谢谢。拥有另一个嵌套现有 DataModel 的数据模型似乎更直接,而不是过滤数据作为响应。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    相关资源
    最近更新 更多