{"id":1030,"date":"2023-10-11T20:02:54","date_gmt":"2023-10-11T17:02:54","guid":{"rendered":"https:\/\/www.juustila.com\/antti\/?p=1030"},"modified":"2023-10-11T20:02:54","modified_gmt":"2023-10-11T17:02:54","slug":"decoding-and-encoding-class-hierarchies-in-swift","status":"publish","type":"post","link":"https:\/\/www.juustila.com\/antti\/2023\/10\/11\/decoding-and-encoding-class-hierarchies-in-swift\/","title":{"rendered":"Decoding and encoding class hierarchies in Swift"},"content":{"rendered":"\n<p>A while ago I was implementing (for fun) a chat client to work with a chat server used in teaching in a GUI programming course. The client is implemented with Swift and SwiftUI.<\/p>\n\n\n\n<p>In the GUI programming course, students get the <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/anttijuu\/O4-server\" target=\"_blank\">server<\/a> and a sample <em>console<\/em> <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/anttijuu\/O4-client\" target=\"_blank\">client<\/a>, both implemented in Java. The goal for the students is to both design and implement a <em>GUI<\/em> chat application. Learning goals are related to GUI design, usability design and implementation of a GUI in a selected language and GUI framework. The server is accessed over TCP and data format is JSON.<\/p>\n\n\n\n<p>One tricky thing was to figure out how the Swift <a rel=\"noreferrer noopener\" href=\"https:\/\/developer.apple.com\/documentation\/swift\/codable\" target=\"_blank\">Codable<\/a> could handle a class structure with a base class <code>Message<\/code>, having different types of messages as subclasses. For example, <code>ChatMessage<\/code> (having the sender, message, timestamp, etc.), a <code>ListChannelsMessage<\/code> (containing the available channels on the server side to join), et cetera.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"338\" src=\"https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-1024x338.png\" alt=\"\" class=\"wp-image-1031\" srcset=\"https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-1024x338.png 1024w, https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-300x99.png 300w, https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-768x254.png 768w, https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-1536x507.png 1536w, https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-2048x676.png 2048w, https:\/\/www.juustila.com\/antti\/wp-content\/uploads\/2023\/10\/O4-chat-client-classes-1200x396.png 1200w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><figcaption class=\"wp-element-caption\">The Java console client class diagram, containing the same message classes as the Swift app.<\/figcaption><\/figure>\n\n\n\n<p>The Swift <code>Codable<\/code> does not directly and simply bend to this kind of a class hierarchy. I searched the net and found a <a rel=\"noreferrer noopener\" href=\"https:\/\/nefkens.net\/swift-json-encoding-decoding-and-subclasses\/\" target=\"_blank\">good basis here<\/a>, but it didn&#8217;t fully show how to do both decoding and encoding with a class structure like I had.<\/p>\n\n\n\n<p>So obviously, for fun, I banged my head against the wall until I got it working. I was supposed to write a blog post about that, but haven&#8217;t had the time.<\/p>\n\n\n\n<p>But today someone in Mastodon asked the exact question; how to do something like this. A good motivation for me to actually do something about that! I didn&#8217;t want to publish the whole Swift Chat client app, since students are still able to start working on this project, and someone might want to select Swift\/SwiftUI as the GUI for their app.<\/p>\n\n\n\n<p>So instead, I extracted the code to show how to use <code>Codable<\/code> and <code>JSONSerialization<\/code> together to handle a class hierarchy like this to encode and decode objects to JSON and back. The code is now available as a <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/anttijuu\/ClassHierarchyCodableSample\" target=\"_blank\">simple example project in GitHub.<\/a> <\/p>\n\n\n\n<p>I shared the repository to the Mastodon discussion. What was exciting for me is that one of the core persons in developing the Swift language itself favourited my reply! ?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A while ago I was implementing (for fun) a chat client to work with a chat server used in teaching in a GUI programming course. The client is implemented with Swift and SwiftUI. In the GUI programming course, students get the server and a sample console client, both implemented in Java. The goal for the &hellip; <a href=\"https:\/\/www.juustila.com\/antti\/2023\/10\/11\/decoding-and-encoding-class-hierarchies-in-swift\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Decoding and encoding class hierarchies in Swift&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[2],"tags":[5,123,126,66,124,70,46,125,12],"class_list":["post-1030","post","type-post","status-publish","format-standard","hentry","category-coding","tag-client-server","tag-codable","tag-gui","tag-json","tag-jsonserialization","tag-programming","tag-swift","tag-tcp","tag-teaching"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/comments?post=1030"}],"version-history":[{"count":1,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1030\/revisions"}],"predecessor-version":[{"id":1032,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1030\/revisions\/1032"}],"wp:attachment":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/media?parent=1030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/categories?post=1030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/tags?post=1030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}