在 Swift 中使用多个相同的标识符解析 JSON
Parsing JSON with multiple identical identifiers in Swift
我正在尝试解析来自 RestAPI 的 JSON 数据,该 API 为我提供挪威的能源数据 (https://driftsdata.statnett.no/restapi/ProductionConsumption/GetLatestDetailedOverview)
<ProductionConsumptionOverviewViewModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Statnett.Driftsdata.RestApi.Models">
<ConsumptionData>
...
</ConsumptionData>
<Headers>
...
</Headers>
<HydroData>
<ProdConsOverViewModelItem>
<style>hydro</style>
<textTranslationId>General.Hydro</textTranslationId>
<titleTranslationId i:nil="true"/>
<value/>
</ProdConsOverViewModelItem>
<ProdConsOverViewModelItem>
<style i:nil="true"/>
<textTranslationId i:nil="true"/>
<titleTranslationId>ProductionConsumption.HydroSEDesc</titleTranslationId>
<value>4 840</value>
我知道它读起来像 XML 但文档说 JSON 所以就这样吧。我在阅读它时遇到了与 XML 相同的问题。
我设法很好地阅读了 JSON 响应,但我无法“挖掘”到正确的位置,因为不同地区的标识符相同。假设我想要下面的 Hydro 生产数据(见屏幕截图)。我怎么会得到那个?我试过设置 [titleTranslationId] == "ProductionConsumption.HydroSEDesc" 但没用。
看起来像 XML 但文档说 JSON ?这就是为什么我试图将其视为 JSON.
<ProductionConsumptionOverviewViewModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Statnett.Driftsdata.RestApi.Models">
<ConsumptionData>
...
</ConsumptionData>
<Headers>
...
</Headers>
<HydroData>
<ProdConsOverViewModelItem>
<style>hydro</style>
<textTranslationId>General.Hydro</textTranslationId>
<titleTranslationId i:nil="true"/>
<value/>
</ProdConsOverViewModelItem>
<ProdConsOverViewModelItem>
<style i:nil="true"/>
<textTranslationId i:nil="true"/>
<titleTranslationId>ProductionConsumption.HydroSEDesc</titleTranslationId>
<value>4 840</value>
API response Screenshot
我正在使用 SwiftyJSON 来处理响应。
我找到了其他一些 但无法让它为我工作。有人能帮忙吗?这是我的代码:
func getEnergyData(url: String){
AF.request(url, method: .get).responseJSON{ response in
switch response.result {
case .success(let json):
print("json success")
//print(json)
let energyJSON : JSON = JSON(response.result)
self.updateEnergyData(json: energyJSON)
case .failure(let error):
print(error)
}
}
}
正在尝试解析它:
func updateEnergyData(json : JSON){
if let results = json["ProductionConsumptionOverviewViewModel"]["HydroData"]["ProdConsOverViewModelItem"]["value"].double{
print(results)
}
else{
print("parse fail")
}
}
}
通过浏览器访问此端点时,API returns XML,否则 returns JSON.
无需 SwiftyJSON 或其他库,而是使用 Swift 的 Codable
协议。
例如,创建一个表示要解码的对象的结构:
struct HydroData: Decodable {
let value: String
let textTranslationId: String?
let titleTranslationId: String?
let style: String?
}
另一个从数组中获取这些对象:
struct HydroResult: Decodable {
let HydroData: [HydroData]
}
然后从端点下载数据后,对其进行解码,然后使用filter
在数组中查找所需的对象:
let url = URL(string: "https://driftsdata.statnett.no/restapi/ProductionConsumption/GetLatestDetailedOverview")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
print("No data")
return
}
do {
let result = try JSONDecoder().decode(HydroResult.self, from: data)
if let seDesc = result.HydroData.filter({ [=12=].titleTranslationId == "ProductionConsumption.HydroSEDesc" }).first {
print(seDesc.value)
} else {
print("Error: no value")
}
} catch {
print(error.localizedDescription)
}
}
task.resume()
注意 value
的 return 类型是字符串,其中的数字已经格式化,因此不能直接将它们转换为 Int 或Double,你必须使用自定义格式化程序,但这是一个完全不同的话题。
我正在尝试解析来自 RestAPI 的 JSON 数据,该 API 为我提供挪威的能源数据 (https://driftsdata.statnett.no/restapi/ProductionConsumption/GetLatestDetailedOverview)
<ProductionConsumptionOverviewViewModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Statnett.Driftsdata.RestApi.Models">
<ConsumptionData>
...
</ConsumptionData>
<Headers>
...
</Headers>
<HydroData>
<ProdConsOverViewModelItem>
<style>hydro</style>
<textTranslationId>General.Hydro</textTranslationId>
<titleTranslationId i:nil="true"/>
<value/>
</ProdConsOverViewModelItem>
<ProdConsOverViewModelItem>
<style i:nil="true"/>
<textTranslationId i:nil="true"/>
<titleTranslationId>ProductionConsumption.HydroSEDesc</titleTranslationId>
<value>4 840</value>
我知道它读起来像 XML 但文档说 JSON 所以就这样吧。我在阅读它时遇到了与 XML 相同的问题。
我设法很好地阅读了 JSON 响应,但我无法“挖掘”到正确的位置,因为不同地区的标识符相同。假设我想要下面的 Hydro 生产数据(见屏幕截图)。我怎么会得到那个?我试过设置 [titleTranslationId] == "ProductionConsumption.HydroSEDesc" 但没用。
看起来像 XML 但文档说 JSON ?这就是为什么我试图将其视为 JSON.
<ProductionConsumptionOverviewViewModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Statnett.Driftsdata.RestApi.Models">
<ConsumptionData>
...
</ConsumptionData>
<Headers>
...
</Headers>
<HydroData>
<ProdConsOverViewModelItem>
<style>hydro</style>
<textTranslationId>General.Hydro</textTranslationId>
<titleTranslationId i:nil="true"/>
<value/>
</ProdConsOverViewModelItem>
<ProdConsOverViewModelItem>
<style i:nil="true"/>
<textTranslationId i:nil="true"/>
<titleTranslationId>ProductionConsumption.HydroSEDesc</titleTranslationId>
<value>4 840</value>
API response Screenshot
我正在使用 SwiftyJSON 来处理响应。
我找到了其他一些
func getEnergyData(url: String){
AF.request(url, method: .get).responseJSON{ response in
switch response.result {
case .success(let json):
print("json success")
//print(json)
let energyJSON : JSON = JSON(response.result)
self.updateEnergyData(json: energyJSON)
case .failure(let error):
print(error)
}
}
}
正在尝试解析它:
func updateEnergyData(json : JSON){
if let results = json["ProductionConsumptionOverviewViewModel"]["HydroData"]["ProdConsOverViewModelItem"]["value"].double{
print(results)
}
else{
print("parse fail")
}
}
}
通过浏览器访问此端点时,API returns XML,否则 returns JSON.
无需 SwiftyJSON 或其他库,而是使用 Swift 的 Codable
协议。
例如,创建一个表示要解码的对象的结构:
struct HydroData: Decodable {
let value: String
let textTranslationId: String?
let titleTranslationId: String?
let style: String?
}
另一个从数组中获取这些对象:
struct HydroResult: Decodable {
let HydroData: [HydroData]
}
然后从端点下载数据后,对其进行解码,然后使用filter
在数组中查找所需的对象:
let url = URL(string: "https://driftsdata.statnett.no/restapi/ProductionConsumption/GetLatestDetailedOverview")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {
print("No data")
return
}
do {
let result = try JSONDecoder().decode(HydroResult.self, from: data)
if let seDesc = result.HydroData.filter({ [=12=].titleTranslationId == "ProductionConsumption.HydroSEDesc" }).first {
print(seDesc.value)
} else {
print("Error: no value")
}
} catch {
print(error.localizedDescription)
}
}
task.resume()
注意 value
的 return 类型是字符串,其中的数字已经格式化,因此不能直接将它们转换为 Int 或Double,你必须使用自定义格式化程序,但这是一个完全不同的话题。