Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Swift可解码解析JSON时出现类型不匹配错误_Json_Swift_Decodable - Fatal编程技术网

使用Swift可解码解析JSON时出现类型不匹配错误

使用Swift可解码解析JSON时出现类型不匹配错误,json,swift,decodable,Json,Swift,Decodable,当我尝试解码JSON时,我得到一个错误: (错误:类型不匹配(Swift.String,Swift.DecodingError.Context)(编码路径:[sweetyanime.Video.(在_D1045E05DE474AEBA8BDCAF57455DC3中编码密钥)。视频,sweetyanime.iD.(在_D1045E05DE474AEBA8BDCAF57455DC3中编码密钥)。iD,sweetyanime.other.(在_D1045E05DE474; AEBA8BDCAF5745

当我尝试解码JSON时,我得到一个错误:

(错误:类型不匹配(Swift.String,Swift.DecodingError.Context)(编码路径:[sweetyanime.Video.(在_D1045E05DE474AEBA8BDCAF57455DC3中编码密钥)。视频,sweetyanime.iD.(在_D1045E05DE474AEBA8BDCAF57455DC3中编码密钥)。iD,sweetyanime.other.(在_D1045E05DE474; AEBA8BDCAF57455DCDCDC3中编码密钥)。视频计数),调试说明:“应解码字符串,但找到了字典。”,underyingError:nil)

1) JSON:

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) 斯威夫特视频

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
}

让我们在错误消息中添加一些换行符,以便于理解:

(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”的值。它需要一个字符串,但找到了一个字典


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

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

(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”的值。它需要一个字符串,但找到了一个字典


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

我认为您应该实现init(从解码器)作为可解码的一部分的初始值设定项。与自动实现相比,它在如何处理嵌套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)
}

这适用于游乐场中的示例数据。我真的不知道您是想要videoCount的键还是值。(对我来说,两者都不像是视频计数。通常,您只需要为嵌套JSON的每一级定义一个CodingKey枚举,您可以根据需要解码各个值。)。(注意,由于我只看到了您的数据的一个示例,这可能会破坏您正在使用的任何API中的某些内容,因此请修改/采纳想法并根据需要重写)

我认为您应该实现init(从解码器)作为可解码的一部分的初始值设定项。与自动实现相比,它在如何处理嵌套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)
}
这适用于游乐场中的示例数据。我真的不知道您是想要videoCount的键还是值。(对我来说,两者都不像是视频计数。通常,您只需要为嵌套JSON的每一级定义一个CodingKey枚举,您可以根据需要解码各个值。)。(注意,由于我只看到了一个数据示例,这可能会破坏您正在使用的任何API中的某些内容,因此请修改/采纳这些想法,并根据需要重新编写)