Codable vs ObjectMapper

Φωτογραφία από https://unsplash.com/photos/_rNVw54xZZg

Πρόσφατα έχω πειραματιστεί με το νέο πρωτόκολλο Codable του Swift ως έναν τρόπο χαρτογράφησης του JSON που τραβήχτηκε από μια απομακρυσμένη υπηρεσία σε ένα πρότυπο μοντέλο Swift.

Για λίγο φόντο, το Codable προστέθηκε στο Swift 4 ως ένας τρόπος για να επιτρέψετε καθαρά στα αντικείμενα να μετατραπούν σε και έξω από μια εξωτερική αναπαράσταση. Το ίδιο το Codable είναι απλώς ένας τύπος Decodable και Encodable.

Για αυτήν την ανάρτηση πρόκειται να επικεντρωθώ στο τμήμα Decodable, καθώς είναι η μετατροπή από μια απομακρυσμένη αναπαράσταση JSON που με ενδιαφέρει.

Σύγκριση

Έχω χρησιμοποιήσει ObjectMapper εκτενώς στο παρελθόν, αλλά όπως Codable είναι τώρα χτισμένο σε Swift ήθελα να κάνω μια σύγκριση των δύο. Τα χαρακτηριστικά που θέλω να συγκρίνω είναι:

  • Επικύρωση ️
  • Προσαρμοσμένη μετασχηματισμός (χαρτογράφηση σε προσαρμοσμένους τύπους, π.χ. αντιστοίχιση μιας συμβολοσειράς JSON σε μια επανάληψη)
  • Διαχείριση σφαλμάτων

Τα δεδομένα που πρόκειται να αναλύσω είναι πραγματικά config που φέρουμε απομακρυσμένα για την εφαρμογή BBC Sport

Είναι μια αρκετά απλή δομή JSON, αλλά έχει μερικές Κανονικές εκφράσεις στο ότι θα ήθελα να αντιστοιχιστεί στο NSRegularExpression, όχι σε String

ObjectMapper

Οι δομές που απαιτούνται για τη χαρτογράφηση αυτού του μοντέλου JSON με ObjectMapper έχουν ως εξής.

Οι κατασκευές συμφωνούν με το πρωτόκολλο ImmutableMappable, πράγμα που σημαίνει ότι χρειάζονται έναν κατασκευαστή που παίρνει ένα αντικείμενο χάρτη και ρίχνει ένα σφάλμα αν η χαρτογράφηση αποτύχει.

Επικύρωση

Για την πραγματοποίηση της επικύρωσης μπορείτε να χρησιμοποιήσετε τα Προαιρετικά. Σε αυτό το παράδειγμα αποφασίσαμε ότι η εφαρμογή μπορεί να λειτουργήσει χωρίς αυτές τις διευθύνσεις ηλεκτρονικού ταχυδρομείου, έτσι ώστε τα μηνύματα ηλεκτρονικού ταχυδρομείου να είναι προαιρετικά. Οι τιμές map.values ​​("emails") ρίχνουν ένα σφάλμα αν το κλειδί δεν υπάρχει ή δεν μπορεί να μεταφερθεί στον σωστό τύπο. Κάνουμε χρήση προσπαθήστε; για να συλλάβει αυτό το σφάλμα και να το μετατρέψει σε τιμή μηδέν εάν υπάρχει κάποιο σφάλμα.

Αν αποφασίσουμε ότι μια συγκεκριμένη ιδιότητα είναι απαραίτητη, τότε δεν την χαρακτηρίζουμε ως προαιρετική και επιτρέπουμε να μεταδοθεί το σφάλμα.

Γενικά, η επικύρωση είναι πολύ ευθεία προς τα εμπρός με τη χρήση του ImmutableMappable

Μπορεί να έχετε παρατηρήσει ότι υπάρχει ένα πρόσθετο επιχείρημα που μεταφέρεται σε αυτή την κλήση map.value ("regex", χρησιμοποιώντας: RegexTransformer ()) Αυτό είναι για το έθιμο μετασχηματισμό για να μετατρέψει το String σε NSRegularExpression που οδηγεί όμορφα μου στο επόμενο σημείο μου!

Προσαρμοσμένη μετατροπή

Το ObjectMapper υποστηρίζει προσαρμοσμένους μετασχηματισμούς από το κουτί και είναι πολύ απλό.

Εδώ εφαρμόζουμε απλώς το πρωτόκολλο TransformType και τη σχετική μέθοδο transformFromJSON. Αυτό παίρνει έναν τύπο και που ρίχνουμε σε String και προσπαθούμε με ασφάλεια; για να μετατρέψετε το String σε NSRegularExpression.

Αυτός ο μετασχηματιστής είναι έπειτα διαθέσιμος για επαναχρησιμοποίηση οπουδήποτε

Αντιμετώπιση σφαλμάτων

Για να ελέγξω το χειρισμό σφαλμάτων, θα χρησιμοποιήσω ένα αρχείο JSON με το κλειδί εξόδου που λείπει.

Όταν τρέχουμε αυτό μέσω του ObjectMapper, έχουμε ένα ωραίο χρήσιμο μήνυμα λάθους έξω.

Παρουσιάστηκε σφάλμα κατά τη χαρτογράφηση.
- λόγος: Δεν μπορεί να μεταφερθεί σε 'String'
- τοποθεσία: Config.init (χάρτη :): 30
- πλήκτρο: έξοδος
- τρέχουσα τιμή: μηδέν

Μας λέει όλα όσα χρειαζόμαστε για να βρούμε γρήγορα το θέμα. Έχω βρει, όταν χρησιμοποιείτε την ενσωμάτωση AlamofireObjectMapper, τα σφάλματα που καταστέλλονται είναι λιγότερο από το ιδανικό.

Κωδικοποιήσιμο

Από το κουτί η ισοδύναμη εφαρμογή Codable είναι η εξής

Είναι πολύ παρόμοιο με το ObjectMapper αν και τα κλειδιά ορίζονται ως enums χρησιμοποιώντας το πρωτόκολλο CodingKey.

Υπάρχει ένα πολύ ωραίο χαρακτηριστικό που χρησιμοποιεί το Codable στο ότι ο αρχικός κώδικας μπορεί να δημιουργηθεί για εσάς αν οι περιπτώσεις enum είναι ίσες με την ιδιότητα και ο τύπος στον οποίο χαρτογραφούμε είναι ο ίδιος Αποδιαμορφώσιμος Ένα παράδειγμα αυτού είναι το CodableConfig παραπάνω. Δεδομένου ότι όλες οι ιδιότητες είναι οι ίδιοι Αποδιαμορφώσιμες δεν χρειάζεται να γράψουμε ένα αρχικοποιητή!

Επικύρωση

Αυτό λειτουργεί ακριβώς όπως το ObjectMapper

Ο αρχικοποιητής ρίχνει ένα σφάλμα εάν υπάρχει μια χαρτογράφηση σφαλμάτων, η οποία μπορεί να αντιμετωπιστεί στον ιστότοπο κλήσεων. Και πάλι, χρησιμοποιήστε τα προαιρετικά εδώ για να αποφασίσετε πώς να χειριστείτε καλύτερα τα λάθη.

Προσαρμοσμένη μετατροπή

Θα παρατηρήσετε στον παραπάνω κώδικα, όλα παίρνουν λίγο λιγότερο σαφή όταν προσπαθούμε να χαρτογραφήσουμε τον τύπο μας NSRegularExpression. Πρέπει ξαφνικά να εφαρμόσουμε τον αρχικό init (από τον αποκωδικοποιητή: Decoder) και να αποκτήσουμε έναν KeyedDecodingContainer από τον αποκωδικοποιητή

Υπάρχει μια μεγάλη εγγραφή για αυτό ήδη αν θέλετε περισσότερες λεπτομέρειες, τις οποίες δεν πρόκειται να πάω εδώ.

Ο κώδικας γίνεται πολύ λεπτομερής για να γράψουμε τώρα και επαναλαμβάνουμε τον κώδικα μετασχηματισμού. Αυτό είναι μόνο μια επιπλέον γραμμή σε αυτή την περίπτωση, αλλά υπάρχουν συχνά φορές που θέλω να γράψω πιο πολύπλοκες μεταμορφώσεις που θα ήθελα να απομονώσω όπως μπορώ με το ObjectMapper

Έτσι, έκανα μια μικρή βιβλιοθήκη για να προσθέσω υποστήριξη για προσαρμοσμένους μετασχηματισμούς αυτό είναι διαθέσιμο μέσω CocoaPods, ή απλά θα μπορούσατε να αντιγράψετε την πηγή επειδή είναι μόνο μερικά αρχεία.

Μπορεί να σκεφτείτε να προσθέσετε μια επέκταση στον τύπο που δεν έχετε, αλλά υπάρχει μια καλή εξήγηση για το γιατί αυτό δεν είναι δυνατό στο Swift Evolution.

Χρησιμοποιώντας τη βιβλιοθήκη CodableExtensions, μπορούμε τώρα να απλουστεύσουμε τον κώδικα μας ώστε να μοιάζει πολύ με τον ObjectMapper

Και ο RegexCodableTransformer είναι επίσης πολύ παρόμοιος με αυτό που είχαμε προηγουμένως με το ObjectMapper

Η βιβλιοθήκη απλοποιεί επίσης τη διασύνδεση στο container.decode (), οπότε ο τύπος δεν χρειάζεται πλέον να διαβιβάζεται όπως υπονοείται.

Αντιμετώπιση σφαλμάτων

Χρησιμοποιώ το ίδιο αρχείο JSON για να συγκρίνω την παράδοση λάθους όπως πριν. Το σφάλμα μοιάζει

κλειδί (config_spike.CodableConfig. (CodingKeys στο _4D474241C6D85B5C48988D77CA644850) .rewriter], debugDescription: "Καμία τιμή που δεν σχετίζεται με την έξοδο του κλειδιού (\" output \ ")., υποκείμενοError: nil))

Το σφάλμα δεν είναι αρκετά ωραίο, αλλά έχει τα πάντα για να εντοπίσει το θέμα.

συμπέρασμα

Υπάρχουν πολύ περισσότερες ομοιότητες από τις διαφορές μεταξύ των δύο προσεγγίσεων. Εάν οι μετασχηματισμοί είναι σημαντικοί, τότε το ObjectMapper λειτουργεί από το κουτί. Ωστόσο, ένα από τα βασικά κίνητρα για την εναλλαγή κινείται προς το πρότυπο που έχει δημιουργήσει η Apple χωρίς να χρειάζεται να φέρει σε άλλη βιβλιοθήκη.

Εάν οι μετασχηματισμοί είναι σημαντικοί, προσθέτοντας μερικά πρωτόκολλα, μπορείτε να πάρετε την ίδια συμπεριφορά με το Codable

Αποφασίσαμε να προχωρήσουμε στο Codable τώρα που όλα τα νέα χαρακτηριστικά μας πηγαίνουν προς τα εμπρός. Είμαι βέβαιος ότι υπάρχουν χαρακτηριστικά που έχω χάσει από αυτή τη λίστα, αλλά διάλεξα τα πιο σημαντικά για εμάς.