如何使用 swift combine 读取嵌套的 json 数据

How can I read the nested json data by using swift combine

我刚开始使用 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 {
                 [=14=].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: [=15=].data, encoding: .utf8) {
                    let dataDic = APIService.convertToDictionary(text: dataString)
                    if let DataArray = dataDic?["data"] {
                        return listDataDic! 
                    }
                 return [=15=].data
                }

请澄清我是否误解了这个问题,但是如果您使用另一个模型解码您的 [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 { [=10=].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)
    }
}