简体   繁体   中英

Using Codable to decode complex json into trivial struct without nested structs

Lets have a json

{
    "channelId": 100,
    "channel_name": "STV 1",
        "stream": {
            "URL": "www.rtvs.sk",
            "DRM": "secureMedia",
            "drmKeys": ["1", "2", "3"],
            "userInfo": {
                "user": "Michal23",
                "userIsTester": true
            }
        }
}

and a struct:

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?
    }
}

I would like to fetch URL from nested stream, but without creating nested struct for it. Is it possible? How?

Looking at the documentation , you can do it but it is more of a manual process than usual. You need to decode the nested container and then extract the information using the coding key.

//: 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)

OUTPUT: Channel(channelId: 100, channelName: "STV 1", channelUrl: www.rtvs.sk))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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