gpt4 book ai didi

ios - 将 JSON 解码为 Codable 对象 - 有条件

转载 作者:行者123 更新时间:2023-11-28 05:41:13 24 4
gpt4 key购买 nike

我想使用 Codable 协议(protocol)将 JSON 解码为对象。

我想要达到的结果是:

[
[ Collection
< collectionType = item
< collectionName = some name`
< data = [ Item
< itemTitle = title
< itemSubtitle = subtitle,
Item
< itemTitle = title
< itemSubtitle = subtitle ],
[ Collection
< collectionType = location
< collectionName = some name`
< data = [ Location
< locationName = someName,
Location
< locationName = someName ],
[ Collection
< collectionType = item
< collectionName = some name`
< data = [ Item
< itemTitle = title
< itemSubtitle = subtitle,
Item
< itemTitle = title
< itemSubtitle = subtitle ],
[ Collection
< collectionType = location
< collectionName = some name`
< data = [ Location
< locationName = someName,
Location
< locationName = someName ]]

JSON如下:

    [{
"collectionType": "item",
"collectionName": "some name",
"data": [
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
},
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
}
]
},
{
"collectionType": "location",
"collectionName": "some name",
"data": [
{
"locationName": "a name",
},
{
"locationName": "a name",
}
]
},
{
"collectionType": "item",
"collectionName": "some name",
"data": [
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
},
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
}
]
},
{
"collectionType": "location",
"collectionName": "some name",
"data": [
{
"locationName": "a name",
},
{
"locationName": "a name",
}
]
}
]

如您所见,集合将属于项目或位置类型。数据将根据该类型。我应该如何使用 Codable 实现这一目标?

我的对象如下:

class Collection: NSObject, Codable {

// MARK: - Properties

let collectionType: String
let collectionName: String
let data????

// MARK: - Keyes

private enum CodingKeys: String, CodingKey {
case collectionType
case collectionName
}
}

class Item: NSObject, Codable {

// MARK: - Properties

let itemTitle: String
let itemSubtitle: String

// MARK: - Keyes

private enum CodingKeys: String, CodingKey {
case itemTitle
case itemSubtitle
}
}

class Location: NSObject, Codable {

// MARK: - Properties

let locationName: String

// MARK: - Keyes

private enum CodingKeys: String, CodingKey {
case locationName
}
}

如何使用适当的对象传播数据?

最佳答案

我建议两种方法:

方法一

更改您的数据结构以消除 data 描述的是项目还是位置的歧义:

[{
"collectionName": "some name",
"items": [
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
},
{
"itemTitle": "title",
"itemSubtitle": "subtitle",
}
]
},
{
"collectionName": "some name",
"locations": [
{
"locationName": "a name",
},
{
"locationName": "another name",
}
]
}]

... 并修改您的 Collection 以具有可选的 locations 和可选的 items

方法二

如果更改您的 JSON 结构不是一个选项,那么我建议将您的 Collection 类更改为:

class Collection: Codable {
let collectionType: String
let collectionName: String
let data: [CollectionData]
}

...并创建一个枚举 CollectionData:

enum CollectionError: Error {
case invalidData
}

enum CollectionData {
case item(Item)
case location(Location)
}

extension CollectionData: Codable {
init(from decoder: Decoder) throws {
if let item = try? Item(from: decoder) {
self = .item(item)
return
}

if let location = try? Location(from: decoder) {
self = .location(location)
return
}

throw CollectionError.invalidData
}

func encode(to encoder: Encoder) throws {
switch self {
case .item(let item):
try item.encode(to: encoder)
case .location(let location):
try location.encode(to: encoder)
}
}
}

两种方法的优缺点:

方法一

优点:使数据更具 self 描述性

缺点:允许集合既没有items也没有locations

方法二

优点:适用于现有数据结构

缺点:将允许 data 数组部分为 Location 部分为 Item

除非您的实际代码有更多内容,否则您似乎将 CodingKeys 定义为与默认值完全相同,因此您可以删除它。

关于ios - 将 JSON 解码为 Codable 对象 - 有条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56668601/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com