如何使用 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)
}
}
我刚开始使用 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)
}
}