{"id":23995,"date":"2019-01-18T14:48:29","date_gmt":"2019-01-18T19:48:29","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=23995"},"modified":"2019-01-24T16:07:49","modified_gmt":"2019-01-24T21:07:49","slug":"even-more-about-swifts-codable","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/01\/18\/even-more-about-swifts-codable\/","title":{"rendered":"Even More About Swift&rsquo;s Codable"},"content":{"rendered":"<p><a href=\"https:\/\/benscheirman.com\/2017\/06\/swift-json\/\">Ben Scheirman<\/a> (via <a href=\"https:\/\/twitter.com\/kuba_suder\/status\/1086002124641759232\">Kuba Suder<\/a>):<\/p>\n<blockquote cite=\"https:\/\/benscheirman.com\/2017\/06\/swift-json\/\">\n<p>Instead, we can use a special method to get a super-class ready encoder that already has a container attached to it[&#8230;]<\/p>\n<p>[&#8230;]<\/p>\n<p>Here we have a <code>migration_date<\/code> field that has a different date format than the <code>created_at<\/code> field. Let&rsquo;s also assume that the name property has since been changed to just <code>name<\/code>.<\/p>\n<p>This is obviously not an ideal situation, but real-life happens and sometimes you inherit a messy API.<\/p>\n<p>[&#8230;]<\/p>\n<p>This is a listing of beer styles, but the keys are actually the name of the style.\nWe could not represent <em>every possible case<\/em> with an enum as it could change or grow over time.<\/p>\n<p>Instead, we can create a more dynamic implementation of <code>CodingKey<\/code> for this.<\/p>\n<\/blockquote>\n<p>This is the most comprehensive guide to <code>Codable<\/code> and JSON that I&rsquo;ve seen.<\/p>\n\n<p><a href=\"http:\/\/www.russbishop.net\/singlevaluecodable\">Russ Bishop<\/a>:<\/p>\n<blockquote cite=\"http:\/\/www.russbishop.net\/singlevaluecodable\">\n<p>The new <code>Codable<\/code> protocol is flexible enough to allow a different encoded representation from the in-memory representation which is a nice property to have in a serialization mechanism. Today I&rsquo;m going to build <code>SingleValueCodable<\/code> to automate that work when dealing with <code>RawRepresentable<\/code> types.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/oleb.net\/blog\/2017\/12\/dictionary-codable-array\/\">Ole Begemann<\/a>:<\/p>\n<blockquote cite=\"https:\/\/oleb.net\/blog\/2017\/12\/dictionary-codable-array\/\">\n<p>So <code>Dictionary<\/code> seems to behave differently depending on its <code>Key<\/code> type, even though the enum values are ultimately encoded as strings. What&rsquo;s going on here? We can find the answer in <a href=\"https:\/\/github.com\/apple\/swift\/blob\/swift-4.1-branch\/stdlib\/public\/core\/Codable.swift.gyb#L1995-L2033\"><code>Dictionary<\/code>&rsquo;s implementation<\/a> for the <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/encodable\"><code>Encodable<\/code><\/a> protocol.<\/p>\n<p>[&#8230;]<\/p>\n<p>There are three branches: only if the dictionary&rsquo;s key type is <code>String<\/code> or <code>Int<\/code> does it use a keyed container. Any other key type triggers results in an unkeyed container of alternating keys and values.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/master\/proposals\/0239-codable-range.md\">SE-0239<\/a>:<\/p>\n<blockquote cite=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/master\/proposals\/0239-codable-range.md\">\n<p><a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/master\/proposals\/0167-swift-encoders.md\">SE-0167<\/a> introduced <code>Codable<\/code> conformance for some types in the standard\nlibrary, but not the <code>Range<\/code> family of types. This proposal adds that\nconformance.<\/p>\n<\/blockquote>\n\n<p>There&rsquo;s quite an interesting <a href=\"https:\/\/forums.swift.org\/t\/se-0239-add-codable-conformance-to-range-types\/18794\">discussion<\/a> about this, because the details of how it works will end up affecting databases and APIs outside of Swift itself.<\/p>\n\n<p><a href=\"https:\/\/paul-samuels.com\/blog\/2019\/01\/02\/swift-heterogeneous-codable-array\/\">Paul Samuels<\/a>:<\/p>\n<blockquote cite=\"https:\/\/paul-samuels.com\/blog\/2019\/01\/02\/swift-heterogeneous-codable-array\/\">\n<p>The two key takeaways here are<\/p>\n<ul>\n<li><p>If you need to represent a collection that can have multiple types then you&rsquo;ll need some form of wrapper and <code>enum<\/code>s can\nperform that duty well when it makes sense.<\/p><\/li>\n<li><p>Swift&rsquo;s <code>Codable<\/code> is really powerful and helped remove a heap of issues that arise from manually parsing\/creating objects.<\/p><\/li>\n<\/ul>\n<p>Removing optionality, reifying types and using compiler generated code are great ways of simplifying our code. In some cases\nthis also helps move runtime crashes into compile time issues, which is generally making our code safer. The benefits here are\ngreat and it shows that it&rsquo;s really worth taking time to model your data correctly and then use tools like <code>Codable<\/code> to munge\nbetween representations.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/paul-samuels.com\/blog\/2019\/01\/07\/swift-codable-testing\/\">Paul Samuels<\/a>:<\/p>\n<blockquote cite=\"https:\/\/paul-samuels.com\/blog\/2019\/01\/07\/swift-codable-testing\/\">\n<p>Testing <code>Codable<\/code> implementations isn&rsquo;t particularly hard but the boilerplate code required can get out of hand pretty quickly. I thought I&rsquo;d run through a TDD process to get to the final solution as I find this stuff personally interesting and hopefully someone else might to. Hopefully I&rsquo;ve highlighted some basic stuff to test when looking at custom <code>Decodable<\/code> implementations and shown that it&rsquo;s useful to refactor not only the production code but the test code as well.<\/p>\n<\/blockquote>\n\n<p>The challenge I see is how to make sure that you don&rsquo;t break compatibility as you evolve your data model.<\/p>\n\n<p id=\"even-more-about-swifts-codable-update-2019-01-24\">Update (2019-01-24): <a href=\"https:\/\/forums.swift.org\/t\/codable-improvements-and-refinements\/19426\">itaiferber<\/a>:<\/p>\n<blockquote cite=\"https:\/\/forums.swift.org\/t\/codable-improvements-and-refinements\/19426\"><p>Hello, everyone! As part of the <a href=\"https:\/\/forums.swift.org\/t\/se-0239-add-codable-conformance-to-range-types\/18794\">review thread for SE-0239<\/a>, we received a lot of helpful feedback that&rsquo;s highlighted areas where we thing Codable can improve, and we wanted to take the time after the holidays to split that conversation aside and help carry it along in a more targeted thread. We think there are a lot of potential improvements to be made, and we&rsquo;re really interested in getting community feedback and contributions to help us get closer to where we&rsquo;ve always wanted Codable to be.<\/p><\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Ben Scheirman (via Kuba Suder): Instead, we can use a special method to get a super-class ready encoder that already has a container attached to it[&#8230;] [&#8230;] Here we have a migration_date field that has a different date format than the created_at field. Let&rsquo;s also assume that the name property has since been changed to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2019-01-18T19:48:32Z","apple_news_api_id":"9effa6a2-7c5d-4418-af1e-e975fe5f0e2b","apple_news_api_modified_at":"2019-01-24T21:07:54Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/Anv-monxdRBivHul1_l8OKw","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[507,71,1774,901,268,50],"class_list":["post-23995","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-json","tag-programming","tag-swift-codable","tag-swift-programming-language","tag-testing","tag-webapi"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23995","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=23995"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23995\/revisions"}],"predecessor-version":[{"id":24058,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/23995\/revisions\/24058"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=23995"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=23995"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=23995"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}