Les nouveaux protocoles Encodable
/Decodable
de Swfit 4 rendent la sérialisation JSON (de) plus agréable. Cependant, je n'ai pas encore trouvé le moyen d'avoir un contrôle précis sur les propriétés qui devraient être codées et celles qui devraient être décodées.
J'ai remarqué qu'exclure la propriété de la variable CodingKeys
qui l'accompagne l'exclut complètement du processus, mais existe-t-il un moyen d'avoir un contrôle plus fin?
La liste des clés à encoder/décoder est contrôlée par un type appelé CodingKeys
. Le compilateur peut synthétiser ceci pour vous mais peut toujours le remplacer.
Disons que vous ne voulez pas encoder/décoder la propriété nickname
:
struct Person: Codable {
var firstName: String
var lastName: String
var nickname: String?
private enum CodingKeys: String, CodingKey {
case firstName
case lastName
}
}
Ceci exclura nickname
lors du codage et décodage.
Si vous voulez qu'il soit asymétrique (c'est-à-dire encoder mais pas décoder ou vice versa), vous devez fournir vos propres implémentations de encode(with encoder: )
et init(from decoder: )
:
struct Person: Codable {
var firstName: String
var lastName: String
// Since fullName is a computed property, it's excluded by default
var fullName: String {
return firstName + " " + lastName
}
private enum CodingKeys: String, CodingKey {
case firstName
case lastName
case fullName
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
firstName = try container.decode(String.self, forKey: .firstName)
lastName = try container.decode(String.self, forKey: .lastName)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(firstName, forKey: .firstName)
try container.encode(lastName, forKey: .lastName)
try container.encode(fullName, forKey: .fullName)
}
}
J'ai utilisé le protocole et son extension avec AssociatedObject pour définir et obtenir une propriété image (ou toute propriété devant être exclue de Codable).
Avec cela, nous n'avons pas à implémenter nos propres encodeurs et décodeurs
Voici le code, en gardant le code pertinent pour plus de simplicité:
protocol SCAttachmentModelProtocol{
var image:UIImage? {get set}
var anotherProperty:Int {get set}
}
extension SCAttachmentModelProtocol where Self: SCAttachmentUploadRequestModel{
var image:UIImage? {
set{
//Use associated object property to set it
}
get{
//Use associated object property to get it
}
}
}
class SCAttachmentUploadRequestModel : SCAttachmentModelProtocol, Codable{
var anotherProperty:Int
}
Maintenant, chaque fois que nous voulons accéder à la propriété Image, nous pouvons utiliser l'objet confirmant le protocole (SCAttachmentModelProtocol).
Bien que cette peut être faite, elle finit par être très unSwifty _ et même un_JSON. Je pense que je vois d'où vous venez, le concept de #id
s est répandu dans HTML, mais il est rarement transféré dans le monde de JSON
que je considère comme une bonne chose _ (TM).
Certaines structures Codable
pourront analyser votre fichier JSON
sans problème si vous le restructurez à l’aide de hachages récursifs, c’est-à-dire si votre recipe
contient uniquement un tableau de ingredients
qui contient (un ou plusieurs) ingredient_info
. De cette façon, l'analyseur vous aidera en premier lieu à assembler votre réseau et il vous suffira de fournir des backlinks via une simple traversée de la structure si vous en avez vraiment besoin. Etant donné que cela nécessite une refonte complète de votre JSON
et votre structure de données, je ne fais que dessiner l’idée pour vous d’y réfléchir. Si vous le jugez acceptable, veuillez me l'indiquer dans les commentaires, je pourrais le développer davantage, mais selon les circonstances, il se peut que vous ne soyez pas libre de changer l'un ou l'autre.
Si nous devons exclure le décodage d'un couple de propriétés d'un grand ensemble de propriétés dans la structure, déclarez-les en tant que propriétés facultatives. Code pour décompresser les options est moins que d’écrire beaucoup de clés sous CodingKey enum.