[英]How to Decode selected keys manually and rest with the automatic decoding with swift Decodable?
Here is the code I am using,这是我正在使用的代码,
struct CreatePostResponseModel : Codable{
var transcodeId:String?
var id:String = ""
enum TopLevelCodingKeys: String, CodingKey {
case _transcode = "_transcode"
case _transcoder = "_transcoder"
}
enum CodingKeys:String, CodingKey{
case id = "_id"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TopLevelCodingKeys.self)
if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcode) {
self.transcodeId = transcodeId
}else if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcoder) {
self.transcodeId = transcodeId
}
}
}
Here, transcodeId
is decided by either _transcode
or _transcoder
.这里, transcodeId
由_transcode
或_transcoder
决定。 But I want id
and rest of the keys (not included here) to be automatically decoded.但我希望自动解码id
和其余键(不包括在此处)。 How can I do it ?我该怎么做 ?
You need to manually parse all the keys once you implement init(from:)
in the Codable
type.在Codable
类型中实现init(from:)
,您需要手动解析所有键。
struct CreatePostResponseModel: Decodable {
var transcodeId: String?
var id: String
enum CodingKeys:String, CodingKey{
case id, transcode, transcoder
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(String.self, forKey: .id) ?? ""
if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcode) {
self.transcodeId = transcodeId
} else if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcoder) {
self.transcodeId = transcodeId
}
}
}
In the above code,在上面的代码中,
Codable
.如果您只想解码JSON ,则无需使用Codable
。 Using Decodable
is enough.使用Decodable
就足够了。enums
for CodingKey
seems unnecessary here.在这里似乎没有必要为CodingKey
使用多个enums
。 You can use a single enum CodingKeys
.您可以使用单个enum CodingKeys
。rawValue
of that case
in enum CodingKeys
.如果属性名和密钥名是完全匹配的,就没有必要明确指定rawValue
是的case
在enum CodingKeys
。 So, there is no requirement of "_transcode"
and "_transcoder"
rawValues
in TopLevelCodingKeys
.因此, TopLevelCodingKeys
不需要"_transcode"
和"_transcoder"
rawValues
。 Apart from all that, you can use keyDecodingStrategy
as .convertFromSnakeCase
to handle underscore notation ( snake case notation ), ie除此之外,您可以使用keyDecodingStrategy
作为.convertFromSnakeCase
来处理下划线符号(蛇大小写符号),即
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase //here.....
let model = try decoder.decode(CreatePostResponseModel.self, from: data)
print(model)
} catch {
print(error)
}
So, you don't need to explicitly handle all the snake-case keys .因此,您不需要显式处理所有蛇形大小写的键。 It'll be handled by the JSONDecoder
on its own.它将由JSONDecoder
自行处理。
This can be one of the good solution for you wherever you want you can add multiple keys for one variable:无论您在何处都可以为一个变量添加多个键,这对您来说都是不错的解决方案之一:
var transcodeId:String?
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
transcodeId = container.getValueFromAvailableKey(codingKeys: [CodingKeys._transcoder,CodingKeys._transcode])
} catch {
print("Error reading config file: \(error.localizedDescription)")
}
}
extension KeyedDecodingContainerProtocol{
func getValueFromAvailableKey(codingKeys:[CodingKey])-> String?{
for key in codingKeys{
for keyPath in self.allKeys{
if key.stringValue == keyPath.stringValue{
do{
return try self.decodeIfPresent(String.self, forKey: keyPath)
} catch {
return nil
}
}
}
}
return nil
}
}
Hope it helps.希望能帮助到你。
The compiler-generated init(from:)
is all-or-nothing.编译器生成的init(from:)
是全有或全无。 You can't have it decode some keys and “manually” decode others.您不能让它解码某些键并“手动”解码其他键。
One way to use the compiler-generated init(from:)
is by giving your struct
both of the possible encoded properties, and make transcodeId
a computed property:使用编译器生成的init(from:)
一种方法是为您的struct
两个可能的编码属性,并使transcodeId
成为计算属性:
struct CreatePostResponseModel: Codable {
var transcodeId: String? {
get { _transcode ?? _transcoder }
set { _transcode = newValue; _transcoder = nil }
}
var _transcode: String? = nil
var _transcoder: String? = nil
var id: String = “”
// other properties
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.