Ios 使用Codable将复杂的json解码为无嵌套结构的平凡结构

Ios 使用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

让我们来看看json

{
    "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。你不需要在“”之后转义。