【问题标题】:Parsing JSON with multiple identical identifiers in Swift在 Swift 中解析具有多个相同标识符的 JSON
【发布时间】:2020-07-19 13:04:52
【问题描述】:

我正在尝试解析来自 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 来处理响应。

我找到了其他一些treads,但无法让它为我工作。有谁能帮忙吗?这是我的代码:

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")
} 
}       
}

【问题讨论】:

  • 那张截图是 xml 而不是 json 你知道吗?你真的应该通过使用Codable 来使用内置的 json 功能,它更现代,更容易在 stackoverflow 获得帮助
  • 是的,我尝试了几次 xml 解析,但根本无法正常工作。文档说“数据为 json”,所以我认为它是:P driftsdata.statnett.no/restapi
  • 是的,但你为什么要发布 xml 作为你问题的一部分?并将示例数据作为文本而不是图像发布
  • api 响应超长,我认为这会更容易看到。我在上面的文本中发布了指向 api 的链接。
  • 如果我搞砸了,我很抱歉,我是这个论坛的新手。对不起

标签: json swift swifty-json


【解决方案1】:

通过浏览器访问此端点时,API 返回 XML,否则返回 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({ $0.titleTranslationId == "ProductionConsumption.HydroSEDesc" }).first {
            print(seDesc.value)
        } else {
            print("Error: no value")
        }
    } catch {
        print(error.localizedDescription)
    }
}
task.resume()

请注意,value 的返回类型是一个字符串,其中的数字已经格式化,因此您不能直接将它们转换为 Int 或 Double,您必须使用自定义格式化程序,但这是一个完全不同的话题。

【讨论】:

  • 谢谢 eric,但是它一直在抱怨它“无法在 JSONDecoder().decode(HydroResult.self) 上将类型 'Data.Type' 的值转换为预期的参数类型 'Data'”,来自:数据)我该如何解决这个问题?
  • @Nisse82 这是因为您的data 类型不正确。我用更完整的示例编辑了我的答案,以便您了解它是如何工作的。不需要 AlamoFire 或 SwiftyJSON 或其他任何东西。
  • 感谢您的所有帮助,但我没有得到“打印(seDesc.value)”来执行。我尝试添加“打印(”值是:(seDesc.value)“)”以查看代码是否运行但没有。我认为 JSON 解码器不能正常工作?
  • @Nisse82 只需在一个新项目中尝试示例代码,这样您就可以看到它工作正常。然后,适应您自己的代码库。查看我的示例的屏幕截图:dropbox.com/s/1mq11n50bwln9a9/… 这给了我“6 052”的值。
  • 哈哈,啊,该死的你是对的。这意味着我搞砸了别的东西:P。谢谢你的帮助,现在是时候去寻找错误了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 2015-02-08
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多