简体   繁体   English

Swift 4 Decodable:解码复杂的JSON

[英]Swift 4 Decodable: Decoding complex JSON

I have to decode an array of the dictionary, where the key is an enum & value is a model object. 我必须解码字典的数组,其中键是枚举,值是模型对象。

Here is my sample JSON, 这是我的示例JSON,

[
  {
    "nanomp4": {
      "url": "https://media.tenor.com/videos/a1da4dcf693c2187615721d866decf00/mp4", 
      "dims": [
        150, 
        138
      ], 
      "duration": 2.0, 
      "preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png", 
      "size": 70381
    }, 
    "nanowebm": {
      "url": "https://media.tenor.com/videos/aa983425114e32ab446f669d91611938/webm", 
      "dims": [
        150, 
        138
      ], 
      "preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png", 
      "size": 53888
    }, 
  },
  {
    "nanomp4": {
    "url": "https://media.tenor.com/videos/a1da4dcf693c2187615721d866decf00/mp4",
    "dims": [
          150,
          138
          ],
    "duration": 2.0,
    "preview": "https://media.tenor.com/images/17d523e6b7c3c9a4ca64566a1890d94d/tenor.png",
    "size": 70381
    },
  }
]

Here is my decoding code, 这是我的解码代码,

do {
    let data = try Data(contentsOf: fileURL)
    let decoder = JSONDecoder()
    let collection = try decoder.decode([[GIFFormat:Media]].self, from: data)

    print(collection)
} catch {
    print("Error in parsing/decoding JSON: \(error)")
}

Here GIFFormat is Enum & Media is the model object, and they are decoding perfectly fine. 这里的GIFFormat是Enum, Media是模型对象,它们解码得很好。

enum GIFFormat: String, Decodable {

    case nanoMP4    = "nanomp4"
    case nanoWebM   = "nanowebm"
}

struct Media: Decodable {
    let url: URL?        
    let dims: [Int]?
    let duration: Double?
    let preview: URL?
    let size: Int64?
}

My console prints, 我的控制台会打印,

typeMismatch(Swift.Array<Any>, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected to decode Array<Any> but found a dictionary instead.", underlyingError: nil))

Can anyone explain to me what is exactly wrong here? 谁能告诉我这里到底有什么问题?

Even though the rawValue for GIFFormat is String , GIFFormat itself is an enum. 即使rawValueGIFFormatStringGIFFormat本身也是一个枚举。 You should update 你应该更新

let collection = try decoder.decode([[GIFFormat:Media]].self, from: data)

to

let collection = try decoder.decode([[GIFFormat.RawValue:Media]].self, from: data)

UPDATE: In response to your comment 更新:回应您的评论

Now to access value, I need to use like this, collection?.first?[GIFFormat.mp4.rawValue]?.url . 现在访问值,我需要像这样使用collection?.first?[GIFFormat.mp4.rawValue]?.url Which is again ugly !! 这又是丑陋!

I would suggest a bit of refactoring. 我建议您进行一些重构。 You can start by removing your enum altogether. 您可以从完全删除enum开始。 Keep your Media struct. 保留您的Media结构。 Create a new Collection struct 创建一个新的Collection结构

struct Collection: Decodable {
    let nanomp4: Media!
    let nanowebm: Media!
}

Then, you can update the above line to 然后,您可以将上面的行更新为

let collection = try decoder.decode([Collection].self, from: data)

and your ugly line transforms into 你的丑陋的线条变成

collection.first?.nanomp4.url

NOTE: This solution assumes that you only have nanomp4 & nanowebm as your enum values. 注意:此解决方案假定您只将nanomp4nanowebm作为枚举值。 If this is not the case, then this might not be the best solution and you might have to go with the first solution. 如果不是这种情况,那么这可能不是最佳解决方案,您可能不得不采用第一个解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM