Swift 结合URLSession和Json解码器AlphaVantage概览数据
我正在尝试使用combine、URLSession获取AlphaVantage股票数据并对其进行解码。我使用了如下的框架。我使用相同的框架成功获取了其他AlphaVantage数据,如损益表和现金流。但是,它不适用于概览数据。我找不到问题出在哪里。我已经为此奋斗了一段时间,如果有人能帮助我,我真的很感激Swift 结合URLSession和Json解码器AlphaVantage概览数据,swift,decode,combine,urlsession,Swift,Decode,Combine,Urlsession,我正在尝试使用combine、URLSession获取AlphaVantage股票数据并对其进行解码。我使用了如下的框架。我使用相同的框架成功获取了其他AlphaVantage数据,如损益表和现金流。但是,它不适用于概览数据。我找不到问题出在哪里。我已经为此奋斗了一段时间,如果有人能帮助我,我真的很感激 import Foundation import Combine var subscriptions = Set<AnyCancellable>() let pub1 = ge
import Foundation
import Combine
var subscriptions = Set<AnyCancellable>()
let pub1 = getCompOverview()
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print(".sink completed")
break
case .failure(let anError):
print("received error: ", anError)
}
}, receiveValue: { receivedValue in
print(".sink() received \(receivedValue)")
})
.store(in: &subscriptions)
func getCompOverview() -> AnyPublisher<CompOverview, Error> {
guard let url = URL(string: "https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=demo") else {
return Fail(error: FetchError.invalidURL).eraseToAnyPublisher()
}
return URLSession.shared.dataTaskPublisher(for: url)
.retry(2)
.tryMap { data, response in
guard
let httpURLResponse = response as? HTTPURLResponse,
httpURLResponse.statusCode == 200
else {
throw URLError(.badServerResponse)
}
print("fetching data size = \(data)")
return data
}
.decode(type: CompOverview.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.eraseToAnyPublisher()
}
struct CompOverview: Codable {
var symbol: String
var name: String
var description: String
var sector: String
var industry: String
var peRatio: String
var pegRatio: String
var forwardPE: String
var eps: String
var divPerShare: String
var divYield: String
var payoutRatio: String
var percentInsiders: String
var percentInstitutions: String
var priceToSalesRatioTTM: String
var marketCapitalization: String
var sharesOutstanding: String
enum CodingKeys: String, CodingKey {
case symbol = "Symbol"
case name = "Name"
case description = "Description"
case sector = "Sector"
case industry = "Industry"
case peRatio = "PERatio"
case pegRatio = "PEGRatio"
case forwardPE = "ForwardPE"
case eps = "EPS"
case divPerShare = "DividendPerShare"
case divYield = "DividendYield"
case payoutRatio = "PayoutRatio"
case percentInsiders = "PercentInsiders"
case percentInstitutions = "PercentInstitutions"
case priceToSalesRatioTTM = "PriceToSalesRatioTTM"
case marketCapitalization = "MarketCapitalization"
case sharesOutstanding = "SharesOutstanding"
}
}
enum FetchError: Error {
case statusCode
case decoding
case invalidImage
case invalidURL
case other(Error)
static func map(_ error: Error) -> FetchError {
return (error as? FetchError) ?? .other(error)
}
<代码>导入基础
进口联合收割机
var subscriptions=Set()
让pub1=getCompOverview()
.sink(receiveCompletion:{completion in
交换完成{
案例。完成:
打印(“水槽已完成”)
打破
案例。失败(让一个错误):
打印(“收到错误:,A错误)
}
},receiveValue:{receivedValue in
打印(“.sink()已接收\(receivedValue)”)
})
.store(位于:&订阅中)
func getCompOverview()->AnyPublisher{
guard let url=url(字符串:https://www.alphavantage.co/query?function=OVERVIEW&symbol=IBM&apikey=demo)其他{
返回失败(错误:FetchError.invalidURL)。橡皮擦到任何发布者()
}
返回URLSession.shared.dataTaskPublisher(用于:url)
.重试(2)
.tryMap{数据,以
警卫
让httpURLResponse=响应为?httpURLResponse,
httpURLResponse.statusCode==200
否则{
抛出URL错误(.badServerResponse)
}
打印(“获取数据大小=\(数据)”)
返回数据
}
.decode(类型:CompOverview.self,解码器:JSONDecoder())
.receive(打开:RunLoop.main)
.删除任何发布者()
}
结构组件视图:可编码{
变量符号:字符串
变量名称:String
变量说明:字符串
var扇区:字符串
var行业:字符串
变量操作:字符串
var比率:字符串
var-forwardPE:String
var-eps:String
var divPerShare:字符串
var-divYield:String
var payoutRatio:字符串
内部人员:字符串
变量:字符串
var priceToSalesRatioTTM:String
var市值:字符串
var sharesOutstanding:String
枚举编码键:字符串,编码键{
case symbol=“symbol”
case name=“name”
案例描述=“描述”
案例扇区=“扇区”
案例行业=“行业”
案例peRatio=“peRatio”
案例PEGRATION=“PEGRATION”
case forwardPE=“forwardPE”
案例eps=“eps”
case divPerShare=“DividendPerShare”
case divYield=“DividendYield”
案例支付率=“支付率”
案例percentInsiders=“percentInsiders”
案例百分比机构=“百分比机构”
案例PriceToSalesratioTM=“PriceToSalesratioTM”
案例marketCapitalization=“marketCapitalization”
案例sharesOutstanding=“sharesOutstanding”
}
}
枚举获取错误:错误{
案例状态代码
案例解码
案例无效图像
案例无效URL
案例其他(错误)
静态函数映射(error:error)->FetchError{
返回(错误为?FetchError)??其他(错误)
}
当我在操场上测试代码时,它在.tryMap闭包中打印了行。但是,.sink没有执行。您需要存储订阅时返回的
anycancelable
实例,否则它将取消订阅。此外,您不需要手动实现解码(from:)
-只需遵循可解码的就足够了。此外,我强烈建议您遵循Swift命名约定,使用camelCase命名属性,例如var dividendPerShare:String
非常感谢您的建议。我添加了。存储,但仍然不起作用。这些名称是键控名称。有办法改变吗e键入的名称?是的。您可以定义一种策略,将密钥转换为camelCase,或手动定义密钥:这是谢谢!请检查如何使代码工作?我只是尝试解码JSON,但由于“EXC_BAD_ACCESS”而失败,它可能被Combine默默吞没。从CompOverview
中删除属性子集修复了它。不确定为什么会发生这种情况-可能是JSON解码器的内部错误