使用 swift 中的 Decodable 提取和解码 json 数据
Extract and decode json data using Decodable in swift
我正在使用外部框架来显示消息列表和详细信息屏幕。
我们无法修改的框架内部消息模型:
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
模型。
好像只通过了list
data/json:
let responseMessage = try JSONDecoder().decode([Message.self], from:
list)
感谢您的帮助和建议!
谢谢
您必须创建负载结构。
struct Data: Decodable {
struct Payload: Decodable {
let msgList: [Message]
}
let data: Payload
}
使用JSON解码器解码JSON。
let responseMessage = try JSONDecoder().decode([Message.self], from: list)
messageList 可以访问使用:responseMessage.data.msgList
这应该很容易,但您需要解码完整的 JSON 对象,除非您想开始覆盖 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?
}
我正在使用外部框架来显示消息列表和详细信息屏幕。
我们无法修改的框架内部消息模型:
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
模型。
好像只通过了list
data/json:
let responseMessage = try JSONDecoder().decode([Message.self], from: list)
感谢您的帮助和建议!
谢谢
您必须创建负载结构。
struct Data: Decodable {
struct Payload: Decodable {
let msgList: [Message]
}
let data: Payload
}
使用JSON解码器解码JSON。
let responseMessage = try JSONDecoder().decode([Message.self], from: list)
messageList 可以访问使用:responseMessage.data.msgList
这应该很容易,但您需要解码完整的 JSON 对象,除非您想开始覆盖 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?
}