Swift JSON 解码器不同类型 [英] Swift JSON decoder different types

查看:45
本文介绍了Swift JSON 解码器不同类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这两个 JSON 对象

<预><代码>[{"name": "热门电影","description": "基本电影描述","类型": "电影","items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]},{"name": "热门电视节目","description": "基本显示说明","type": "电视节目","items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]}]

然后我为节目和电影创建了两个可解码的结构:

struct 电影:可解码 {让 ID:Int让名称:字符串让电影SPT:字符串}struct TVShow:可解码{让 ID:Int让名称:字符串让 showSPT:字符串}

那么,当我为主要响应创建一个对象时,根据类型值创建 items 数组的最佳方法是什么?我知道我可以为某些独特的结构创建带有可选属性的 showSPT 和 movieSPT,但这是正确的方法吗?另外,如果这两个模型的属性很多,那么combine结构体就太大了.

结构块:可解码{让名称:字符串让描述:字符串让类型:字符串让项目:[电影] 或 [显示] 基于类型????}

解决方案

有几个解决方案.其中之一是具有关联类型的枚举

让 jsonString = """[{名称":热门电影",描述":基本电影描述",类型":电影","items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]},{"name": "热门电视节目", "description": "基本节目说明", "type": "tvshows","items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]}]"""让数据 = 数据(jsonString.utf8)结构电影:可解码{让 ID:Int让名称,电影SPT:字符串}struct TVShow:可解码{让 ID:Int让名称,显示SPT:字符串}枚举媒体类型{案例电影([电影]), tvShow([TVShow])}结构媒体:可解码{让名称:字符串让描述:字符串让项目:MediaType私有枚举 CodingKeys : String, CodingKey { case name, description, type, items }init(来自解码器:解码器)抛出{让容器 = 尝试decoder.container(keyedBy: CodingKeys.self)self.name = try container.decode(String.self, forKey: .name)self.description = 尝试 container.decode(String.self, forKey: .description)让 type = try container.decode(String.self, forKey: .type)如果类型==电影"{let movieData = try container.decode([Movie].self, forKey: .items)项目 = .movi​​e(movieData)} else {//添加更好的错误处理让 showData = try container.decode([TVShow].self, forKey: .items)项目 = .tvShow(showData)}}}做 {让结果 = 尝试 JSONDecoder().decode([Media].self, from: data)打印(结果)} 抓住 {打印(错误)}

I have these two JSON objects

[ 
{"name": "Popular Movies", 
"description": "Basic movie description", 
"type": "movies", 
"items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]
},
{"name": "Popular TV Shows", 
"description": "Basic shows description", 
"type": "tvshows", 
"items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]
}
]

Then i created two decodable structs, for shows and for movies:

struct Movie: Decodable {
    let id: Int
    let name: String
    let movieSPT: String
}

struct TVShow: Decodable {
    let id: Int
    let name: String
    let showSPT: String
}

So, when i create an object for main response, what is the best way to create an items array depends on type value? I know i can create both showSPT and movieSPT with optional properties for some unique struct, but is it the right way? Also, if these two models will have a lot of properties, the combine struct will be too big.

struct Blocks : Decodable {
    let name: String
    let description: String
    let type: String
    let items: [Movie] or [Show] based on type????
}

解决方案

There are a couple of solutions. One of them is an enum with associated types

let jsonString = """
[{"name": "Popular Movies", "description": "Basic movie description", "type": "movies",
    "items": [ { "id": 15, "name": "Sample movie", "movieSPT": ""}]
},
{"name": "Popular TV Shows", "description": "Basic shows description", "type": "tvshows",
"items": [ { "id": 15, "name": "Sample show", "showSPT": ""}]
}
]
"""
let data = Data(jsonString.utf8)


struct Movie : Decodable {
    let id: Int
    let name, movieSPT: String
}

struct TVShow : Decodable {
    let id: Int
    let name, showSPT: String
}

enum MediaType {
    case movie([Movie]), tvShow([TVShow])
}

struct Media : Decodable {
    let name : String
    let description : String
    let items : MediaType

    private enum CodingKeys : String, CodingKey { case name, description, type, items }

    init(from decoder : Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        self.description = try container.decode(String.self, forKey: .description)
        let type = try container.decode(String.self, forKey: .type)
        if type == "movies" {
            let movieData = try container.decode([Movie].self, forKey: .items)
            items = .movie(movieData)
        } else { // add better error handling
            let showData = try container.decode([TVShow].self, forKey: .items)
            items = .tvShow(showData)
        }

    }
}

do {
    let result = try JSONDecoder().decode([Media].self, from: data)
    print(result)
} catch {
    print(error)
}

这篇关于Swift JSON 解码器不同类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆