我想使用可编码协议将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
}
}
如何传播带有适当对象的数据?
答案 0 :(得分:1)
我建议两种方法:
更改数据结构以消除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)
}
}
}
两种方法的优缺点:
专业版:使数据更具描述性
骗局:不允许同时使用items
和locations
专业版:使用现有数据结构
缺点:将允许部分为data
和部分Location
的{{1}}数组
除非您的真实代码有更多内容,否则您似乎完全按照默认设置来定义Item
,因此可以将其删除。
答案 1 :(得分:0)
建议不要使用条件解析,而应使用具有多个具有可选值的属性的公共类,并根据需要使用它。请参考下面的代码。
例如,如果itemTitle
是nil
,则执行locationName
的逻辑,依此类推。
class Collection: NSObject, Codable {
let collectionType: String
let collectionName: String
let data:data?
private enum CodingKeys: String, CodingKey {
case collectionType
case collectionName
}
}
class data: NSObject, Codable {
let itemTitle: String?
let itemSubtitle: String?
let locationName: String?
private enum CodingKeys: String, CodingKey {
case itemTitle
case itemSubtitle
case locationName
}
}