基于另一个值的具有多个对象类型的可编码解码属性 [英] Codable decode property with multiple object types BASED on another value
问题描述
这与解码多种类型(int,字符串)的属性值无关.
It's not about decoding a property value with multiple types (int, string)..
我有一个名为 data
的对象,它可以返回多种类型,这时可以做的事情可能看起来像这样:
I have an object called data
it can return multiple types, What could be done at this point may look something like this :
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
,因此可以确定要解码的内容
The issue here is that i try to make MyData
decode the object based on another value that was used in the previous decoding process, in short words, i want to pass a value to MyData
so it can determine which to decode
我有这个
enum ContentType: String, Codable {
case linear
case grid
case slider
}
我想让 MyData
知道此 ContentType
值,以便 MyData
可以确定流程的进行方式,
And i want MyData
to know about this ContentType
value so MyData
can determine how the flow will go,
那么ContentType是从哪里来的呢?它位于上一个主对象的相同属性列表中,来自类似这样的东西
So where did ContentType come from ? it's in the same list of properties in the previous main object, coming from something that looks like this
struct Catalog: Codable {
var dataType: ContentType?
var data: MyData?
}
我想用更简单的语言实现什么?
What i want to achieve in more simple words ?
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
--------- JSON i want to parse
[{
"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的值返回不同的对象
You see the point above, is that "data" can return different objects, based on the value of data_type
推荐答案
我没有使用泛型,而是创建了一个符合 Decodable
的空协议,并将其用作 data的类型代码>.然后,内容结构需要符合此协议.
Rather than using generics I created an empty protocol that conforms to Decodable
and used that as the type for data
. Then the content structs needs to conform to this protocol.
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)
}
}
}
请注意,我没有在 init
中使用枚举 ContentType
,因为它与示例json数据不匹配,但是应该易于修复.
Note that I didn't use the enum ContentType
in the init
because it didn't match the sample json data but that should be easily fixed.
使用此解决方案的标准代码
Standard code for using this solution
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode([Catalog].self, from: data)
print(result)
} catch {
print(error)
}
这篇关于基于另一个值的具有多个对象类型的可编码解码属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!