[英]Decode json array data with different datatypes in IOS using struct decodable swift 4/5
[英]Extract and decode json data using Decodable in swift
我正在使用一个外部框架来显示消息列表和详细信息屏幕。
框架内部消息 model 我们无法修改:
public struct Message: Decodable, Encodable {
public var id: String?
public var title: String?
public var subTitle: String?
public var status: String?
}
我们的 API 响应:
{
"data":{
"custId":"1234",
"type":"premium",
"totalCount":"100",
"msgList":[
{
"id":"1",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
},
{
"id":"2",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
}
],
"categoryCount":"50"
}
}
如何从 JSON 响应中提取msgList
数组并解码为Message
model。
仅传递list
数据/json之类的东西:
let responseMessage = try JSONDecoder().decode([Message.self], from: list)
感谢您的帮助和建议!
谢谢
您必须创建有效负载结构。
struct Data: Decodable {
struct Payload: Decodable {
let msgList: [Message]
}
let data: Payload
}
使用 JSONDecoder 解码 JSON。
let responseMessage = try JSONDecoder().decode([Message.self], from: list)
messageList 可以使用: responseMessage.data.msgList
访问
这应该很容易,但是您需要解码完整的 JSON object ,除非您想开始覆盖init(from decoder:)
方法并手动执行一些操作。
试图从 JSON 中仅提取消息数组会比它的价值更麻烦。
import UIKit
let jsonData = """
{
"data":{
"custId":"1234",
"type":"premium",
"totalCount":"100",
"msgList":[
{
"id":"1",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
},
{
"id":"2",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
}
],
"categoryCount":"50"
}
}
""".data(using: .utf8)
struct Root: Decodable {
let data: Customer
}
struct Customer: Decodable {
let custId: String
let type: String
let totalCount: String
let msgList: [Message]
}
public struct Message: Decodable, Encodable {
public var id: String?
public var title: String?
public var subTitle: String?
public var status: String?
}
do {
let result = try JSONDecoder().decode(Root.self, from: jsonData!)
print(result)
} catch {
print(error)
}
您可以访问这样的消息:
let messages = result.data.msgList
应该看起来像这样:
// MARK: - Root
struct Root: Codable {
let data: DataClass
}
// MARK: - DataClass
struct DataClass: Codable {
let custID, type, totalCount: String
let msgList: [MsgList]
let categoryCount: String
enum CodingKeys: String, CodingKey {
case custID = "custId"
case type, totalCount, msgList, categoryCount
}
}
// MARK: - MsgList
struct MsgList: Codable {
let id, title, subTitle, status: String
}
然后加载您的数据:
let list: [String : Any] = [:] // load data accordingly...
if let responseMessage = try JSONDecoder().decode(Root.self, from: list)
{
// responseMessage.data.msgList
}
Class 名称只是一个示例,请随意重命名它们。
你可以试试
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let str = """
{
"data":{
"custId":"1234",
"type":"premium",
"totalCount":"100",
"msgList":[
{
"id":"1",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
},
{
"id":"2",
"title":"Main Title",
"subTitle":"Sub title",
"status":"R"
}
],
"categoryCount":"50"
}
}
"""
do {
let res = try JSONDecoder().decode(Root.self, from:Data(str.utf8))
print(res.list)
}
catch {
print(error)
}
}
}
struct Root : Decodable {
let list : [Message]
struct AnyCodingKey : CodingKey {
var stringValue: String
var intValue: Int?
init(_ codingKey: CodingKey) {
self.stringValue = codingKey.stringValue
self.intValue = codingKey.intValue
}
init(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
init(from decoder: Decoder) throws {
var con = try! decoder.container(keyedBy: AnyCodingKey.self)
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"data"))
let res = try! con.decode([Message].self, forKey: AnyCodingKey(stringValue:"msgList"))
self.list = res
}
}
struct Message: Codable {
let id,title,subTitle,status: String?
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.