Comment puis-je personnaliser les touches avec Swift 4 Décodable protocole?
Swift 4 introduit la prise en charge native de codage et décodage JSON via le Décodable
protocole. Comment puis-je personnaliser les touches pour cela?
E. g., dire que j'ai un struct
struct Address:Codable {
var street:String
var zip:String
var city:String
var state:String
}
Je peux encoder ce JSON.
let address = Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
if let encoded = try? encoder.encode(address) {
if let json = String(data: encoded, encoding: .utf8) {
//Print JSON String
print(json)
//JSON string is
{ "state":"California",
"street":"Apple Bay Street",
"zip":"94608",
"city":"Emeryville"
}
}
}
Je peux encoder ce retour à un objet.
let newAddress: Address = try decoder.decode(Address.self, from: encoded)
Mais Si j'avais un objet json qui a été
{
"state":"California",
"street":"Apple Bay Street",
"zip_code":"94608",
"city":"Emeryville"
}
Comment pourrais-je dire le décodeur sur Address
que zip_code
cartes à zip
? Je crois que vous utilisez le nouveau CodingKey
protocole, mais je ne peux pas comprendre comment les utiliser.
Vous devez vous connecter pour publier un commentaire.
Manuellement, la personnalisation des clés de codage
Dans votre exemple, vous avez une auto-généré, de la conformité à
Codable
que tous vos biens soient aussi conformes à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 un vraiment fonction propre 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 untypealias
avec ce nom), qui est conforme à laCodingKey
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.Ce que cela signifie est que vous pouvez simplement dire:
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 valeurs brutes d'un
String
énumération sera le même que le cas des noms). Par conséquent, lazip
propriété sera désormais codés/décodés à l'aide de la clé"zip_code"
.Les règles exactes pour l'auto-générés
Encodable
/Décodable
la conformité sont détaillées par l'évolution de la proposition (l'emphase est mienne):Exemple de codage:
Exemple de décodage:
Automatique
snake_case
JSON clés pourcamelCase
noms de propriétéDans Swift 4.1, si vous renommez votre
zip
propriétézipCode
, vous pouvez prendre avantage de la clé de codage/décodage des stratégies surJSONEncoder
etJSONDecoder
afin de convertir automatiquement les clés de codage entrecamelCase
etsnake_case
.Exemple de codage:
Exemple de décodage:
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 la Swift API lignes directrices de conception, doit être uniformément cas supérieure ou inférieure (selon le poste).
Par exemple, une propriété nommée
someURL
sera codé avec la clésome_url
, mais sur le décodage, ce sera transforméesomeUrl
.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
someUrl
dans ce cas (qui va encore être transformé àsome_url
par le codeur):(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 sur
JSONEncoder
etJSONDecoder
, vous permettant de fournir une fonction personnalisée à la carte des clés de codage.La fonction que vous fournissez prend un
[CodingKey]
, 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 unCodingKey
qui va remplacer la dernière touche à ce tableau.Par exemple,
UpperCamelCase
JSON clés pourlowerCamelCase
noms de propriété:Vous pouvez coder avec le
.convertToUpperCamelCase
clés de la stratégie:et décoder avec la
.convertFromUpperCamelCase
clés de la stratégie:CodingKeys
enum; puis-je la liste l'une des clés, je suis en train de changer?"""
est un multi-ligne littérale 🙂"
s 😀"""
:).Codable
contraire)address.street
?street
clé de laAddress
, je voudrais juste faireJSONDecoder().decode(Address.self, from: jsonData).street
. Vous pourrait probablement utiliser les types imbriqués afin de faire par exemple.decode(Address.Street.self, from: jsonData)
, mais je n'ai pas tout de suite voir comment vous pourriez le faire sans duplication de clésstruct
s pour chaque couche? De sorte que dans le imbriquésCodingKeys
enum
vous pouvez spécifiercase address = "person.house.address"
(dans certainsCodable
) sans avoir à créerPerson
etHouse
struct
s si le JSON avait unAddress
imbriqués sous{ "person": { ... "house": { ... "address": { "state":... } } } }
.additionalInfo
.Address
inutilement les liens vous permettant de décoder un objet JSON qui commence à un endroit spécifique dans le parent de l'objet graphique. Il serait beaucoup plus agréable à l'abstrait la clé de départ du chemin jusqu'à le décodeur lui-même – voici un accidenté de la hackey-ish mise en œuvre.percent_change_24h
. À l'aide de.convertFromSnakeCase
j'ai essayépercentChange24h
mais je suis nul. Mon serpent d'autres cas, sans chiffres de travail c'est à diremarket_cap
àmarketCap
si cela semble être un problème avec les chiffres..capitalized
bien sur(NS)String
pour transformer chaque de la non-premières composantes (ceux qui sont séparés par des underscores) de la clé."24h".capitalized
retourne"24H"
, si vous voulezpercentChange24H
(vous pouvez ajouter ce que l'un codage personnalisé clé si vous souhaitez que votre propriété de rester d'être nommépercentChange24h
).case volume24h = "volume_24h"
mais j'étais encore voir nul dans la sortie. Des idées pourquoi? Je n'ai cependant avoir du succès avec le modifiant pour les majuscules comme vous l'avez dit. Incroyable! Où avez-vous trouvez cette info sur la interne de l'info? Merci.case volume24h = "volume24H"
. Et la mise en œuvre de laconvertFromSnakeCase
clé de la stratégie est disponible ici 🙂AnyCodingKey
n'est pas une partie de la bibliothèque standard (mais vraiment, il devrait il être!), J'ai défini dans une version antérieure du bloc de code dans ma réponse.codingKeys.last
vous donne actuelle de la clé de codage, tous les éléments précédents dans le tableau de parents, de clés de codage pour le codage chemin. Par exemple lors du décodage de{"foo": {"bar": "baz"}}
, lorsque la clé de décodage de la stratégie est appliquée à"bar"
,codingKeys
sera["foo", "bar"]
.Avec Swift 4.2, selon vos besoins, vous pouvez utiliser l'une des 3 stratégies suivantes dans le but de rendre vos objets de modèle personnalisé de la propriété des noms correspondent à vos JSON clés.
#1. En utilisant des clés de codage
Lorsque vous déclarez une structure conforme à
Codable
(Decodable
etEncodable
protocoles) à la suite de la mise en œuvre...... le compilateur génère automatiquement un imbriquée enum qui est conforme à
CodingKey
protocole pour vous.Par conséquent, si les clés utilisés dans votre format de données sérialisées ne correspondent pas à la propriété des noms de votre type de données, vous pouvez manuellement mettre en œuvre cette enum et définir les
rawValue
pour le cas.L'exemple suivant montre comment faire:
Coder (en remplacement de
zip
propriété avec "zip_code" JSON clé):Décoder (en remplaçant "zip_code" JSON clé avec
zip
la propriété):#2. À l'aide de serpent cas de chameau cas de la clé des stratégies de codage
Si votre JSON a de serpent enfermé les clés et que vous souhaitez les convertir en camelcase les propriétés de votre objet de modèle, vous pouvez définir votre
JSONEncoder
'skeyEncodingStrategy
etJSONDecoder
'skeyDecodingStrategy
propriétés à.convertToSnakeCase
.L'exemple suivant montre comment faire:
Encoder (conversion camelcase propriétés en serpent tubé JSON touches):
Décoder (conversion de serpent tubé JSON clés en camelcase propriétés):
#3. À l'aide d'une clé personnalisée stratégies de codage
Si nécessaire,
JSONEncoder
etJSONDecoder
vous permettent de définir une stratégie personnalisée à la carte des clés de codage à l'aide deJSONEncoder.KeyEncodingStrategy.personnalisé(_:)
etJSONDecoder.KeyDecodingStrategy.personnalisé(_:)
.L'exemple suivant montre comment les mettre en œuvre:
Encoder (conversion en lowercase premières propriétés de la lettre en en majuscule la première lettre JSON touches):
Décoder (conversion en majuscule la première lettre JSON clés en lowercase premières propriétés de la lettre):
Sources:
Ce que j'ai fait c'est de créer de structure propre, tout comme ce que vous obtenez à partir du JSON à l'égard de ses types de données.
Comme cela:
Après cela, vous devez créer une extension de la même
struct
l'extension dedecodable
et laenum
de la même structure avecCodingKey
et ensuite, vous devez initialiser le décodeur à l'aide de cette enum, avec ses clés et types de données (Clés viendra de l'enum et les types de données sera de venir ou de dire référencé à partir de la structure elle-même)Vous avez besoin de changer ici chaque clé et les types de données en fonction de vos besoins et de l'utiliser avec le décodeur.
En utilisant CodingKey vous pouvez utiliser des clés dans codable ou déchiffrable protocole.