Swift Codable

编程入门 行业动态 更新时间:2024-10-05 13:18:56
本文介绍了Swift Codable-解析JSON数组,可以包含不同的数据类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试解析一个可以是

I am trying to parse a JSON array which can be

{ "config_data": [ { "name": "illuminate", "config_title": "Blink" }, { "name": "shoot", "config_title": "Fire" } ] }

也可以是以下类型

{ "config_data": [ "illuminate", "shoot" ] }

甚至

{ "config_data": [ 25, 100 ] }

因此,为了使用JSONDecoder对此进行解析,我创建了一个结构如下-

So to parse this using JSONDecoder I created a struct as follows -

Struct Model: Codable { var config_data: [Any]? enum CodingKeys: String, CodingKey { case config_data = "config_data" } init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) config_data = try values.decode([Any].self, forKey: .config_data) } }

但这无法正常工作,因为任何都无法确认可解码协议.这可能是解决方案.数组可以包含任何类型的数据

But this would not work since Any does not confirm to decodable protocol. What could be the solution for this. The array can contain any kind of data

推荐答案

我使用了 quicktype 推断config_data的类型,它建议为您的对象,字符串和整数值使用单独的大小写的枚举:

I used quicktype to infer the type of config_data and it suggested an enum with separate cases for your object, string, and integer values:

struct ConfigData { let configData: [ConfigDatumElement] } enum ConfigDatumElement { case configDatumClass(ConfigDatumClass) case integer(Int) case string(String) } struct ConfigDatumClass { let name, configTitle: String }

这是完整的代码示例.解码enum有点棘手,但是quicktype可以帮助您解决问题:

Here's the complete code example. It's a bit tricky to decode the enum but quicktype helps you out there:

// To parse the JSON, add this file to your project and do: // // let configData = try? JSONDecoder().decode(ConfigData.self, from: jsonData) import Foundation struct ConfigData: Codable { let configData: [ConfigDatumElement] enum CodingKeys: String, CodingKey { case configData = "config_data" } } enum ConfigDatumElement: Codable { case configDatumClass(ConfigDatumClass) case integer(Int) case string(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let x = try? container.decode(Int.self) { self = .integer(x) return } if let x = try? container.decode(String.self) { self = .string(x) return } if let x = try? container.decode(ConfigDatumClass.self) { self = .configDatumClass(x) return } throw DecodingError.typeMismatch(ConfigDatumElement.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ConfigDatumElement")) } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .configDatumClass(let x): try container.encode(x) case .integer(let x): try container.encode(x) case .string(let x): try container.encode(x) } } } struct ConfigDatumClass: Codable { let name, configTitle: String enum CodingKeys: String, CodingKey { case name case configTitle = "config_title" } }

使用enum很高兴,因为这样可以得到最大的类型安全性.其他答案似乎都没有.

It's nice to use the enum because you get the most type-safety that way. The other answers seem to lose this.

使用quicktype的便捷初始化程序选项,一个有效的代码示例为:

Using quicktype's convenience initializers option, a working code sample is:

let data = try ConfigData(""" { "config_data": [ { "name": "illuminate", "config_title": "Blink" }, { "name": "shoot", "config_title": "Fire" }, "illuminate", "shoot", 25, 100 ] } """) for item in data.configData { switch item { case .configDatumClass(let d): print("It's a class:", d) case .integer(let i): print("It's an int:", i) case .string(let s): print("It's a string:", s) } }

此打印:

It's a class: ConfigDatumClass(name: "illuminate", configTitle: "Blink") It's a class: ConfigDatumClass(name: "shoot", configTitle: "Fire") It's a string: illuminate It's a string: shoot It's an int: 25 It's an int: 100

更多推荐

Swift Codable

本文发布于:2023-11-26 23:26:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1635638.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Swift   Codable

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!