Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何手动解码选定的密钥,并使用swift Decodable自动解码?_Ios_Swift_Codable_Decodable_Encodable - Fatal编程技术网

Ios 如何手动解码选定的密钥,并使用swift Decodable自动解码?

Ios 如何手动解码选定的密钥,并使用swift Decodable自动解码?,ios,swift,codable,decodable,encodable,Ios,Swift,Codable,Decodable,Encodable,这是我正在使用的代码 struct CreatePostResponseModel : Codable{ var transcodeId:String? var id:String = "" enum TopLevelCodingKeys: String, CodingKey { case _transcode = "_transcode" case _transcoder = "_transcoder" } enum Co

这是我正在使用的代码

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
        }

    }
}
这里,
transcodeId
\u transcode
\u transcoder
决定。
但是我希望
id
和其余的键(这里不包括)被自动解码。如何操作?

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
        }
    }
}
在上述代码中

  • 如果您只想解码JSON,则无需使用
    Codable
    。使用可解码的
    就足够了
  • 这里似乎没有必要为
    CodingKey
    使用多个
    enum
    。您可以使用单个
    枚举编码键
  • 如果属性名和键名完全匹配,则无需在
    enum CodingKeys
    中明确指定该
    case
    rawValue
    。因此,在
    TopLevelCodingKeys
    中不需要
    “\u transcode”
    “\u transcoder”
    rawValues
  • 除此之外,您还可以使用
    keyDecodingStrategy
    作为
    .convertFromSnakeCase
    来处理下划线符号(snake-case-notation),即


    因此,您不需要显式地处理所有的snake-case密钥。它将由
    JSONDecoder
    自行处理。

    这是一个很好的解决方案,您可以在任何地方为一个变量添加多个键:

    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
        }
    }
    

    希望有帮助。

    编译器生成的
    init(from:)
    要么全是,要么全是。你不能让它解码一些键,而“手动”解码其他键

    使用编译器生成的
    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
    }
    

    你还需要手动解码其他密钥。谢谢你的回复,第1点:我也需要可编码,反之亦然。2:如果我在CodingKeys中保留了更多的键,而没有相应的变量,则会出现编译错误。3:属性名来自两个值(_transcoder和_transcode)中的任何一个。不完全是这样,我必须解码所有键:(是的,你必须这么做。你最好修改API以给出一致的响应。绝对同意。
    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
    }