【问题标题】:How to parse this type of data to a JSON in Swift?如何在 Swift 中将这种类型的数据解析为 JSON?
【发布时间】:2021-07-05 05:08:21
【问题描述】:

我调用了一个 API 来获取一年中的所有假期,结果是 Json 类型。但我只能像下面这样提取它(它是“项目”的众多元素之一)

"items": [
  {
   "kind": "calendar#event",
   "etag": "\"3235567993214000\"",
   "id": "20200101_1814eggq09ims8ge9pine82pclgn49rj41262u9a00oe83po05002i01",
   "status": "confirmed",
   "htmlLink": "https://www.google.com/calendar/event?eid=MjAyMDAxMDFfMTgxNGVnZ3EwOWltczhnZTlwaW5lODJwY2xnbjQ5cmo0MTI2MnU5YTAwb2U4M3BvMDUwMDJpMDEgZW4udWsjaG9saWRheUB2",
   "created": "2021-04-07T08:26:36.000Z",
   "updated": "2021-04-07T08:26:36.607Z",
   "summary": "New Year's Day",
   "creator": {
    "email": "en.uk#holiday@group.v.calendar.google.com",
    "displayName": "Holidays in United Kingdom",
    "self": true
   },
   "organizer": {
    "email": "en.uk#holiday@group.v.calendar.google.com",
    "displayName": "Holidays in United Kingdom",
    "self": true
   },
   "start": {
    "date": "2020-01-01"
   },
   "end": {
    "date": "2020-01-02"
   },
   "transparency": "transparent",
   "visibility": "public",
   "iCalUID": "20200101_1814eggq09ims8ge9pine82pclgn49rj41262u9a00oe83po05002i01@google.com",
   "sequence": 0,
   "eventType": "default"
  },
  {
   "kind": "calendar#event",
   "etag": "\"3235567993214000\"",
   "id": "20200412_1814eggq09ims8gd8lgn6t35e8g56tbechgniag063i0ue048064g0g",
   "status": "confirmed",
   "htmlLink": "https://www.google.com/calendar/event?eid=MjAyMDA0MTJfMTgxNGVnZ3EwOWltczhnZDhsZ242dDM1ZThnNTZ0YmVjaGduaWFnMDYzaTB1ZTA0ODA2NGcwZyBlbi51ayNob2xpZGF5QHY",
   "created": "2021-04-07T08:26:36.000Z",
   "updated": "2021-04-07T08:26:36.607Z",
   "summary": "Easter Sunday",
   "creator": {
    "email": "en.uk#holiday@group.v.calendar.google.com",
    "displayName": "Holidays in United Kingdom",
    "self": true
   },
   "organizer": {
    "email": "en.uk#holiday@group.v.calendar.google.com",
    "displayName": "Holidays in United Kingdom",
    "self": true
   },
   "start": {
    "date": "2020-04-12"
   },
   "end": {
    "date": "2020-04-13"
   },
   "transparency": "transparent",
   "visibility": "public",
   "iCalUID": "20200412_1814eggq09ims8gd8lgn6t35e8g56tbechgniag063i0ue048064g0g@google.com",
   "sequence": 0,
   "eventType": "default"
  }

我尝试获取键“start”和键“summary”中的值,但我不能。

Xcode 告诉我“items”是__NSArrayI 类型。

到目前为止我尝试过的是创建一个像这样简单的类(只是先尝试​​使用,所以我没有让所有变量都变)

class API_Info {
var kind: String?
var etag: String?
var id: String?
var status: String?
var htmlLink: String?
var created: String?
var updated: String?
var summary: String?

init(items: [String:Any]){
    self.kind = items["kind"] as? String
    self.etag = items["etag"] as? String
    self.id = items["id"] as? String
    self.status = items["status"] as? String
    self.htmlLink = items["htmlLink"] as? String
    self.created = items["created"] as? String
    self.updated = items["updated"] as? String
    self.summary = items["summary"] as? String
 }
}

我这样解析:

guard let items = json!["items"]! as? [API_Info] else{
                print("null")
            return
        }

这样,else语句就运行了。

我做错了什么,我怎样才能得到我想要的数据?

提前致谢。

【问题讨论】:

  • 我猜json!["items"]! 不是[API_Info],而是[[String: Any]]。不是因为您施放(使用as?),它才会调用您的init(items:) 方法。您需要调用该方法。但是你为什么不使用 Codable?
  • 请将您的 json 作为文本而不是图像发布
  • 哦,我忘了 Codable。但是你是什么意思“你需要调用那个方法”?,我还没有理解,对不起。
  • 我刚刚编辑了我的问题。谢谢。
  • guard let itemsDictionaries = json!["items"] as? [[String: Any]] else { print(" json![\"items\"] isn't an array of Dictionaries"); return } let items = itemsDictionaries.map { API_Infos.init(items: $0) } 应该会更好。但如果有的话,更喜欢Codable

标签: json swift api nsarray


【解决方案1】:

Codable 是这里的解决方案。下面是我使用的结构而不是你的类

struct ApiInfo: Codable {
    let kind: String
    let etag: String
    let id: String
    let status: String
    let htmlLink: String
    let created: Date 
    let updated: Date
    let summary: String
}

然后我创建了一个根类型来保存数组

struct Result: Codable {
    let items: [ApiInfo]
}

然后解码

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

do {
    let result = try decoder.decode(Result.self, from: data)
    print(result.items)
} catch {
    print(error)
}

请注意,数据值被解码为Date 对象。 (可选)您可以跳过根类型并解码为字典

do {
    let items = try decoder.decode([String: [ApiInfo]].self, from: data)
    if let values = items["items"] {
        print(values)
    }
} catch {
    print(error)
}

【讨论】:

    猜你喜欢
    • 2019-10-06
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    相关资源
    最近更新 更多