这与解码具有多种类型(int,字符串)的属性值无关。
我有一个名为data
的对象,它可以返回多种类型,这时可以做的事情可能看起来像这样:
enum MyData: Codable {
case ObjOne(groupObject)
case ObjTwo(imageObject)
init(from decoder: Decoder) throws {
let value = try decoder.singleValueContainer()
if let v = try? value.decode(groupObject.self) {
self = .ObjOne(v)
return
} else if let v = try? value.decode(imageObject.self) {
self = .ObjTwo(v)
return
}
throw Rating.ParseError.notRecognizedType(value)
}
enum ParseError: Error {
case notRecognizedType(Any)
}
}
这里的问题是我试图根据先前解码过程中使用的另一个值使MyData
解码对象,简而言之,我想将一个值传递给MyData
,所以它可以确定要解码的内容
我有这个
enum ContentType: String, Codable {
case linear
case grid
case slider
}
我希望MyData
知道这个ContentType
的值,以便MyData
可以确定流量的流向,
那么ContentType是从哪里来的?它位于上一个主对象的相同属性列表中,来自类似这样的东西
struct Catalog: Codable {
var dataType: ContentType?
var data: MyData?
}
我想用更简单的语言实现什么?
struct Catalog: Codable {
var dataType: ContentType?
var data: MyData<dataType>? <--// i know this is not possible,
// -- but i want MyData to know about the dataType value that will be decoded
}
---------我要解析的JSON
[{
"data_type": "group",
"data": {
"group_id": 127 // this refers to object : groupObject
}
},
{
"data_type": "image",
"data": {
"image": "http://google.com/favicon" // this is referring : imageObject
}
}
]
您看到了上面的观点,即“数据”可以基于data_type的值返回不同个对象
答案 0 :(得分:1)
我没有使用泛型,而是创建了一个符合Decodable
的空协议,并将其用作data
的类型。然后内容结构需要符合此协议。
protocol MyData: Decodable {}
struct Group: MyData {
let groupId: Int
}
struct Image: MyData {
let image: String
}
struct Catalog: Decodable {
var dataType: String
var data: MyData
enum CodingKeys: String, CodingKey {
case dataType, data
}
enum ParseError: Error {
case notRecognizedType(Any)
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
dataType = try container.decode(String.self, forKey: .dataType)
switch dataType {
case "group":
data = try container.decode(Group.self, forKey: .data)
case "image":
data = try container.decode(Image.self, forKey: .data)
default:
throw ParseError.notRecognizedType(dataType)
}
}
}
请注意,我没有在ContentType
中使用枚举init
,因为它与示例json数据不匹配,但这应该很容易解决。
使用此解决方案的标准代码
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode([Catalog].self, from: data)
print(result)
} catch {
print(error)
}