在 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,你必须使用自定义格式化程序,但这是一个完全不同的话题。