使用Swift Decodable解析JSON时输入Mismatch错误

时间:2018-03-15 00:41:24

标签: json swift decodable

当我尝试解码JSON时,我收到错误:

  

(错误:typeMismatch(swift.String,Swift.DecodingError.Context(codingPath:[sweetyanime.Video。(CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).video,sweetyanime.iD。(CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).ID,sweetyanime.other。( CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).CountOfVideos],debugDescription:“预计会解码String而是找到一个字典。”,underlyingError:nil)

1)JSON:

{ "video":{  

  "ID":{ 

     "Name":"NameOfAnime",
     "Describe":"SomeDescribe",
     "Image":"https://firebasestorage.googleapis.com/v0/b/sweety-anime-e6bb4.appspot.com/o/main.png?alt=media&token=042a2dad-8519-4904-9ba3-262c2c962434",
     "CountOfVideos":{  
        "1Series":"https://firebasestorage.googleapis.com/v0/b/sweety-anime-e6bb4.appspot.com/o/message_movies%252F12323439-9729-4941-BA07-2BAE970967C7.movalt=media&token=978d8b3a-7aad-468f-87d4-2b587d616720"
     }
  } } }

2)Swift代码:

let jsonUrl = "file:///Users/tima/WebstormProjects/untitled/db.json"
guard let url = URL(string: jsonUrl) else { return }

URLSession.shared.dataTask(with: url) { (data, reponse, error) in
    guard let data = data else {return}
    do {
        let video = try
            JSONDecoder().decode(Video.self, from: data)
        print(video.video.ID.Name)
    } catch let jsonErr {
        print("Error: ", jsonErr)
    }
}.resume()

3)Video.swift

struct Video: Decodable {
   private enum CodingKeys : String, CodingKey { case video = "video" 
   }
   let video: iD
}

struct iD: Decodable {
   private enum CodingKeys : String, CodingKey { case ID = "ID" }
   let ID: other
}

struct other: Decodable {
   private enum CodingKeys : String, CodingKey {
      case Name = "Name"
      case Describe = "Describe"
      case Image = "Image"
      case CountOfVideos = "CountOfVideos"
   }
   let Name: String
   let Describe: String
   let Image: String
   let CountOfVideos: String
}

2 个答案:

答案 0 :(得分:3)

让我们在您的错误消息中添加一些换行符以使其易于理解:

(Error: typeMismatch(Swift.String,
    Swift.DecodingError.Context(codingPath: [
        sweetyanime.Video.(CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).video,
        sweetyanime.iD.(CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).ID,
        sweetyanime.other.(CodingKeys in _D1045E05CDE474AEBA8BDCAF57455DC3).CountOfVideos],
    debugDescription: "Expected to decode String but found a dictionary instead.",
    underlyingError: nil)

所以它试图解码“CountOfVideos”的值。它期待一个String,但它找到了一个字典。

您需要定义与“CountOfVideos”字典对应的struct(它似乎包含一个键,“1Series”,带有字符串值),或者您需要删除CountOfVideos来自other结构的属性,因此您根本不会尝试对其进行解码。

答案 1 :(得分:-1)

我认为你应该实现init(解码器)初始化器,它是Decodable的一部分。它为处理嵌套JSON提供了比自动实现更多的灵活性。一种可能的实现方式如下:

struct Video: Decodable {
let name: String
let describe: String
let image: String
let countOfVideos: String

private enum VideoKey: String, CodingKey {
    case video = "video"
}

private enum IDKey: String, CodingKey {
    case id = "ID"
}

private enum CodingKeys: String, CodingKey {
    case name = "Name"
    case describe = "Describe"
    case image = "Image"
    case countOfVideos = "CountOfVideos"
}

private enum VideoCountKey: String, CodingKey {
    case videoCount = "1Series"
}

init(from decoder: Decoder) throws {
    let videoContainer = try decoder.container(keyedBy: VideoKey.self)
    let idContainer = try videoContainer.nestedContainer(keyedBy: IDKey.self, forKey: .video)
    let valuesContainer = try idContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .id)
    self.name = try valuesContainer.decode(String.self, forKey: .name)
    self.describe = try valuesContainer.decode(String.self, forKey: .describe)
    self.image = try valuesContainer.decode(String.self, forKey: .image)
    let videoCountContainer = try valuesContainer.nestedContainer(keyedBy: VideoCountKey.self, forKey: .countOfVideos)
    self.countOfVideos = try videoCountContainer.decode(String.self, forKey: .videoCount)
}

这适用于Playground中的示例数据。我真的不知道你是否想要你的videoCount的密钥或价值。 (对我来说,它们看起来都不是一个视频计数。通常,你只需要为嵌套JSON的每个级别定义一个CodingKey枚举,你可以根据需要解码各个值。(注意,因为我只看到一个例子对于你的数据,这可能会破坏你正在使用的任何API中的某些东西,所以修改/接受这些想法并根据需要重写它们。