Manuellement, la personnalisation des clés de codage
Dans votre exemple, vous avez une auto-généré, de la conformité à Codable
que l'ensemble de vos propriétés également respecter Codable
. Cette conformité crée automatiquement un type de clé qui correspond tout simplement à la propriété des noms – qui est ensuite utilisé pour encoder pour/décodage à partir d'une clé unique conteneur.
Cependant, l'un vraiment agréable de cette auto-généré à la conformité de l'est que si vous définissez une imbriqués enum
dans votre type appelé "CodingKeys
" (ou utiliser un typealias
avec ce nom), qui est conforme à l' CodingKey
protocole Swift utilise automatiquement ce que le type de clé. Ceci permet donc de facilement personnaliser les clés de vos propriétés sont codés/décodés avec.
Donc, ce que cela signifie est que vous pouvez simplement dire:
struct Address : Codable {
var street: String
var zip: String
var city: String
var state: String
private enum CodingKeys : String, CodingKey {
case street, zip = "zip_code", city, state
}
}
L'énumération des noms de cas besoin de faire correspondre les noms de propriété, et les valeurs brutes de ces cas besoin de faire correspondre les touches que vous êtes de l'encodage/décodage à partir de (sauf si spécifié autrement, les premières valeurs de String
énumération sera le même que le cas des noms). Par conséquent, l' zip
de la propriété sera désormais codés/décodés à l'aide de la touche "zip_code"
.
Les règles exactes pour l'auto-générés Encodable
/Decodable
de conformité sont détaillées en fonction de l'évolution de la proposition (l'emphase est mienne):
En plus automatiques CodingKey
exigence de synthèse pour
enums
, Encodable
& Decodable
exigences peuvent être automatiquement
synthétisé pour certains types ainsi:
Types conformes à l' Encodable
dont les propriétés sont tous Encodable
obtenir généré automatiquement String
-backed CodingKey
enum cartographie
propriétés à des noms de cas. De même, pour l' Decodable
, dont
les propriétés sont tous Decodable
Types de tomber dans (1) - et de types de fournir manuellement une CodingKey
enum
(nommé en CodingKeys
, directement ou par l'intermédiaire d'un typealias
) dont
cas de la carte 1-à-1 Encodable
/Decodable
propriétés par nom - get
automatique de la synthèse de l' init(from:)
et encode(to:)
comme il convient,
l'utilisation de ces propriétés et des touches de
Les Types qui tombent dans ni (1) ni (2) devra fournir une clé personnalisée de type si nécessaire et de fournir leurs propres init(from:)
et
encode(to:)
, selon le cas
Exemple d'encodage:
import Foundation
let address = Address(street: "Apple Bay Street", zip: "94608",
city: "Emeryville", state: "California")
do {
let encoded = try JSONEncoder().encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
Exemple de décodage:
// using the """ multi-line string literal here, as introduced in SE-0168,
// to avoid escaping the quotation marks
let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoded = try JSONDecoder().decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zip: "94608",
// city: "Emeryville", state: "California")
Automatique snake_case
JSON clés pour camelCase
noms de propriété
Dans Swift 4.1, si vous renommez votre zip
de la propriété d' zipCode
,, vous pouvez profiter de la clé de codage/décodage des stratégies JSONEncoder
et JSONDecoder
afin de convertir automatiquement les clés de codage entre camelCase
et snake_case
.
Exemple d'encodage:
import Foundation
struct 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 encoder = JSONEncoder()
Exemple de décodage:
encoder.keyEncodingStrategy = .convertToSnakeCase
Une chose importante à noter à propos de cette stratégie, cependant, est qu'il ne sera pas en mesure d'aller-retour de certains noms de propriété avec les acronymes ou sigles qui, selon l' API Swift lignes directrices de conception, doit être uniformément cas supérieure ou inférieure (selon le poste).
Par exemple, une propriété nommée
let encoded = try encoder.encode(address)
print(String(decoding: encoded, as: UTF8.self))
} catch {
print(error)
}
//{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
sera codé avec la clé let jsonString = """
{"state":"California","street":"Apple Bay Street","zip_code":"94608","city":"Emeryville"}
"""
do {
let decoder = JSONDecoder()
, mais sur le décodage, ce sera transformée en decoder.keyDecodingStrategy = .convertFromSnakeCase
.
Pour résoudre ce problème, vous devez spécifier manuellement la clé de codage pour cette propriété à la chaîne que le décodeur s'attend, e.g
let decoded = try decoder.decode(Address.self, from: Data(jsonString.utf8))
print(decoded)
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zipCode: "94608",
// city: "Emeryville", state: "California")
dans ce cas (qui va encore être transformé someURL
par le codeur):
some_url
(Ce qui n'est pas strictement répondre à une question particulière, mais compte tenu de la canoniques de la nature de ce Q&A, je pense que c'est utile notamment)
Personnalisé automatique JSON mappage de touches
Dans Swift 4.1, vous pouvez profiter de la coutume de la clé de codage/décodage des stratégies someUrl
et someUrl
, vous permettant de fournir une fonction personnalisée à la carte des clés de codage.
La fonction que vous fournissez prend un some_url
, ce qui représente le codage chemin d'accès pour le point en cours de codage/décodage (dans la plupart des cas, vous aurez seulement besoin de considérer le dernier élément, qui est, à la clé). La fonction retourne un struct S : Codable {
private enum CodingKeys : String, CodingKey {
case someURL = "someUrl", someOtherProperty
}
var someURL: String
var someOtherProperty: String
}
qui va remplacer la dernière touche à ce tableau.
Par exemple, JSONEncoder
JSON clés pour JSONDecoder
noms de propriété:
[CodingKey]
CodingKey
UpperCamelCase
Vous pouvez coder avec l' lowerCamelCase
clés de la stratégie:
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
}
}
et décoder avec l' extension JSONEncoder.KeyEncodingStrategy {
static var convertToUpperCamelCase: JSONEncoder.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
}
}
}
clés de la stratégie:
extension JSONDecoder.KeyDecodingStrategy {
static var convertFromUpperCamelCase: JSONDecoder.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
}
}
}