在您的示例中,
Codable由于所有属性也都符合,因此您将获得自动生成的符合
Codable。这种一致性会自动创建一个仅与属性名称相对应的密钥类型,然后将其用于对单个密钥容器进行编码/解码。
但是,这种自动生成的一致性的一个 真正 巧妙的功能是,如果您
enum在称为“
CodingKeys”
的类型中定义一个嵌套(或使用
typealias具有此名称的a)来符合
CodingKey协议,则Swift将自动将
其 用作键类型。因此,这使您可以轻松自定义用于对属性进行编码/解码的键。
因此,这意味着您可以说:
struct Address : Codable { var street: String var zip: String var city: String var state: String private enum CodingKeys : String, CodingKey { case street, zip = "zip_pre", city, state }}
枚举案例名称需要与属性名称匹配,并且这些案例的原始值需要与您要编码/解码的键匹配(除非另有指定,否则
String枚举的原始值将与案例名称相同)。因此,
zip现在将使用key
对属性进行编码/解码
"zip_pre"。
有关自动生成
Encodable/
Decodable一致性的确切规则,请参见演进提案(重点是我的):
除了的自动
CodingKey需求综合外enums,Encodable&Decodable需求还可以针对某些类型自动综合:1.
符合Encodable所有属性的类型将Encodable获得自动生成的String支持的CodingKey枚举,将枚举属性映射到案例名称。对于Decodable所有属性都相同的类型也是如此Decodable
属于(1)的 类型
CodingKeyenum``CodingKeys``typealias``Encodable``Decodable- 以及手动提供类型
(名称为 ,直接或通过a )将其案例 按名称 一对一映射到 / 属性的类型 -
使用这些属性和键自动进行合并,init(from:)并enpre(to:)在适当时进行合并落入类型既不(1)也没有(2)将具有如果需要的话提供一个自定义的密钥类型和提供它们自己的
init(from:)和enpre(to:),如适当
编码示例:
import Foundationlet address = Address(street: "Apple Bay Street", zip: "94608",city: "Emeryville", state: "California")do { let enpred = try JSonEnprer().enpre(address) print(String(decoding: enpred, as: UTF8.self))} catch { print(error)}//{"state":"California","street":"Apple Bay Street","zip_pre":"94608","city":"Emeryville"}
解码示例:
// using the """ multi-line string literal here, as introduced in SE-0168,// to avoid escaping the quotation markslet jsonString = """{"state":"California","street":"Apple Bay Street","zip_pre":"94608","city":"Emeryville"}"""do { let depred = try JSonDeprer().depre(Address.self, from: Data(jsonString.utf8)) print(depred)} catch { print(error)}// Address(street: "Apple Bay Street", zip: "94608",// city: "Emeryville", state: "California")
属性名称的自动
snake_caseJSON键
camelCase
在雨燕4.1,如果您重命名
zip属性
zipCode,你可以利用关键的编码/解码上的策略
JSONEnprer,并
JSONDeprer以自动转换之间的编码键
camelCase和
snake_case。
编码示例:
import Foundationstruct Address : Codable { var street: String var zipCode: String var city: String var state: String}let address = Address(street: "Apple Bay Street", zipCode: "94608",city: "Emeryville", state: "California")do { let enprer = JSonEnprer() **enprer.keyEncodingStrategy = .convertToSnakeCase** let enpred = try enprer.enpre(address) print(String(decoding: enpred, as: UTF8.self))} catch { print(error)}//{"state":"California","street":"Apple Bay Street","zip_pre":"94608","city":"Emeryville"}
解码示例:
let jsonString = """{"state":"California","street":"Apple Bay Street","zip_pre":"94608","city":"Emeryville"}"""do { let deprer = JSonDeprer() **deprer.keyDecodingStrategy = .convertFromSnakeCase** let depred = try deprer.depre(Address.self, from: Data(jsonString.utf8)) print(depred)} catch { print(error)}// Address(street: "Apple Bay Street", zipCode: "94608",// city: "Emeryville", state: "California")
但是,有关此策略的重要注意事项是,它无法使用首字母缩写词或首字母缩写来循环某些属性名称,根据Swift
API设计指南,这些属性名称应统一使用大写或小写(取决于位置) )。
例如,名为的属性
someURL将使用键进行编码
some_url,但是在解码时,它将转换为
someUrl。
要解决此问题,您必须手动将该属性的编码键指定为解码器期望的字符串,例如,
someUrl在这种情况下(
some_url编码器仍将其转换为):
struct S : Codable { private enum CodingKeys : String, CodingKey { case someURL = "someUrl", someOtherProperty } var someURL: String var someOtherProperty: String}
(这并不能严格回答您的特定问题,但是鉴于此问答的典型性质,我认为值得考虑)
自定义自动JSON密钥映射在雨燕4.1,您可以利用自定义按键编码/解码上的策略
JSONEnprer和
JSONDeprer,使您可以提供一个自定义函数映射的编码键。
您提供的函数采用
[CodingKey],代表编码/解码中当前点的编码路径(在大多数情况下,您只需要考虑最后一个元素;即当前键)。该函数返回一个
CodingKey,它将替换此数组中的最后一个键。
例如,属性名称的
UpperCamelCaseJSON键
lowerCamelCase:
import Foundation// wrapper to allow us to substitute our mapped string keys.struct AnyCodingKey : CodingKey { var stringValue: String var intValue: Int? init(_ base: CodingKey) { self.init(stringValue: base.stringValue, intValue: base.intValue) } init(stringValue: String) { self.stringValue = stringValue } init(intValue: Int) { self.stringValue = "(intValue)" self.intValue = intValue } init(stringValue: String, intValue: Int?) { self.stringValue = stringValue self.intValue = intValue }}
extension JSONEnprer.KeyEncodingStrategy { static var convertToUpperCamelCase: JSONEnprer.KeyEncodingStrategy { return .custom { codingKeys in var key = AnyCodingKey(codingKeys.last!) // uppercase first letter if let firstChar = key.stringValue.first { let i = key.stringValue.startIndex key.stringValue.replaceSubrange( i ... i, with: String(firstChar).uppercased() ) } return key } }}
extension JSONDeprer.KeyDecodingStrategy { static var convertFromUpperCamelCase: JSONDeprer.KeyDecodingStrategy { return .custom { codingKeys in var key = AnyCodingKey(codingKeys.last!) // lowercase first letter if let firstChar = key.stringValue.first { let i = key.stringValue.startIndex key.stringValue.replaceSubrange( i ... i, with: String(firstChar).lowercased() ) } return key } }}
您现在可以使用以下
.convertToUpperCamelCase关键策略进行编码:
let address = Address(street: "Apple Bay Street", zipCode: "94608",city: "Emeryville", state: "California")do { let enprer = JSonEnprer() enprer.keyEncodingStrategy = .convertToUpperCamelCase let enpred = try enprer.enpre(address) print(String(decoding: enpred, as: UTF8.self))} catch { print(error)}//{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}
并采用以下
.convertFromUpperCamelCase关键策略进行解码:
let jsonString = """{"Street":"Apple Bay Street","City":"Emeryville","State":"California","ZipCode":"94608"}"""do { let deprer = JSonDeprer() deprer.keyDecodingStrategy = .convertFromUpperCamelCase let depred = try deprer.depre(Address.self, from: Data(jsonString.utf8)) print(depred)} catch { print(error)}// Address(street: "Apple Bay Street", zipCode: "94608",// city: "Emeryville", state: "California")
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)