基于另一个值的具有多种对象类型的可编码解码属性
Posted
技术标签:
【中文标题】基于另一个值的具有多种对象类型的可编码解码属性【英文标题】:Codable decode property with multiple object types BASED on another value 【发布时间】:2019-09-04 09:37:57 【问题描述】:这与解码具有多种类型(int、string)的属性值无关..
我有一个名为 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”可以根据data_type的值返回不同的个对象
【问题讨论】:
您应该在问题中包含一些示例 JSON。 @DávidPásztor 你是对的,这让它变得更好了,我已经包含了一个 JSON。 【参考方案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)
请注意,我没有在 init
中使用枚举 ContentType
,因为它与示例 json 数据不匹配,但这应该很容易修复。
使用此解决方案的标准代码
do
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let result = try decoder.decode([Catalog].self, from: data)
print(result)
catch
print(error)
【讨论】:
以上是关于基于另一个值的具有多种对象类型的可编码解码属性的主要内容,如果未能解决你的问题,请参考以下文章