Ios 使用Codable将复杂的json解码为无嵌套结构的平凡结构
让我们来看看jsonIos 使用Codable将复杂的json解码为无嵌套结构的平凡结构,ios,json,swift,Ios,Json,Swift,让我们来看看json { "channelId": 100, "channel_name": "STV 1", "stream": { "URL": "www.rtvs.sk", "DRM": "secureMedia", "drmKeys": ["1", "2", "3"], "userInfo": { "user": "Michal2
{
"channelId": 100,
"channel_name": "STV 1",
"stream": {
"URL": "www.rtvs.sk",
"DRM": "secureMedia",
"drmKeys": ["1", "2", "3"],
"userInfo": {
"user": "Michal23",
"userIsTester": true
}
}
}
和一个结构:
struct Channel : Codable {
var channelId : Int
var channelName : String
var channelUrl : URL
private enum CodingKeys : String, CodingKey {
case channelId
case channelName = "channel_name"
case channelUrl = "URL" <===??? json path somehow?
}
}
struct通道:可编码{
var channelId:Int
var channelName:String
var channelUrl:URL
私有枚举编码键:字符串,编码键{
病例通道ID
case channelName=“频道名称”
case channelUrl=“URL”查看,您可以这样做,但这更像是一个手动过程。您需要解码嵌套容器,然后使用编码键提取信息
//: Playground - noun: a place where people can play
import UIKit
let jsonData = """
{
"channelId": 100,
"channel_name": "STV 1",
"stream": {
"URL": "www.rtvs.sk"
}
}
""".data(using: String.Encoding.utf8)!
struct Channel {
var channelId : Int
var channelName : String
var channelUrl: URL
private enum CodingKeys : String, CodingKey {
case channelId
case channelName = "channel_name"
case stream
}
private enum AdditionalInfoKeys: String, CodingKey {
case channelUrl = "URL"
}
}
extension Channel: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
channelId = try values.decode(Int.self, forKey: .channelId)
channelName = try values.decode(String.self, forKey: .channelName)
let additionalInfo = try values.nestedContainer(keyedBy: AdditionalInfoKeys.self, forKey: .stream)
channelUrl = try additionalInfo.decode(URL.self, forKey: .channelUrl)
}
}
let decoder = JSONDecoder()
let channel = try? decoder.decode(Channel.self, from: jsonData)
print(channel)
输出:频道(频道ID:100,频道名称:“STV 1”,频道URL:www.rtvs.sk))
查看,您可以这样做,但这更像是一个手动过程。您需要解码嵌套的容器,然后使用编码键提取信息
//: Playground - noun: a place where people can play
import UIKit
let jsonData = """
{
"channelId": 100,
"channel_name": "STV 1",
"stream": {
"URL": "www.rtvs.sk"
}
}
""".data(using: String.Encoding.utf8)!
struct Channel {
var channelId : Int
var channelName : String
var channelUrl: URL
private enum CodingKeys : String, CodingKey {
case channelId
case channelName = "channel_name"
case stream
}
private enum AdditionalInfoKeys: String, CodingKey {
case channelUrl = "URL"
}
}
extension Channel: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
channelId = try values.decode(Int.self, forKey: .channelId)
channelName = try values.decode(String.self, forKey: .channelName)
let additionalInfo = try values.nestedContainer(keyedBy: AdditionalInfoKeys.self, forKey: .stream)
channelUrl = try additionalInfo.decode(URL.self, forKey: .channelUrl)
}
}
let decoder = JSONDecoder()
let channel = try? decoder.decode(Channel.self, from: jsonData)
print(channel)
输出:频道(频道ID:100,频道名称:“STV 1”,频道URL:www.rtvs.sk))
您需要使用嵌套结构,因为这是JSONDecoder和codable协同工作的方式。有像ObjectMapper这样的外部库,允许您添加像“streams.URL”这样的json路径但是JSONDecoder没有。不过,您可以按照此处所述使用Decodable手动解码它并获取嵌套信息:我担心这是唯一的方法。谢谢您的评论。请参阅上面更新的评论,有一种方法,但更为手动。感谢您将我踢向正确的方向。帮助很大。您需要使用嵌套结构,因为这就是JSOND的方式ecoder和codable一起工作。有一些外部库,如ObjectMapper,允许您添加json路径,如“streams.URL”但是JSONDecoder没有。不过,你可以按照这里的描述用Decodable手动解码它,并获得嵌套信息:我担心这是唯一的方法。谢谢你的评论。请参阅上面更新的评论,有一种方法,但更为手动。谢谢你把我踢向正确的方向。帮助很大。是的,就是这样。我提出了几乎相同的解决方案,除了t表示初始值设定项不在扩展中,而是在结构本身中。是否有一些值使其在扩展中?(如果它不是您的代码,是的,但当它是您可以随意编辑的所有代码)P.S.您不需要在“之后”转义。是的,就是这样。我提出了几乎相同的解决方案,除了初始值设定项不在扩展中,而是在结构本身。它在扩展中有什么价值吗?(如果它不是你的代码,是的,但当它是你所有的代码时,你可以随意编辑)P.S。你不需要在“”之后转义。