{"id":73,"date":"2023-11-19T19:53:13","date_gmt":"2023-11-19T12:53:13","guid":{"rendered":"https:\/\/sekjell.com\/swift\/?p=73"},"modified":"2023-11-19T19:53:13","modified_gmt":"2023-11-19T12:53:13","slug":"make-swiftdata-codable","status":"publish","type":"post","link":"https:\/\/sekjell.com\/swift\/2023\/11\/19\/make-swiftdata-codable\/","title":{"rendered":"Make SwiftData Codable"},"content":{"rendered":"\n<p>When moving from Core Data to Swift Data, it&#8217;s not obvious how to make the data model codable, a must for reading or writing JSON files or API&#8217;s to\/from the persistent storage.<\/p>\n\n\n\n<p>A way to do it is to manually add Codekeys so that the @Model knows that the data types are supported. Here is the code<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"import SwiftUI\nimport SwiftData\n\n@Model\nclass Persons: Codable {\n    enum CodingKeys: CodingKey {\n        case firstName, lastName, phoneNumber\n    }\n    let firstName: String\n    let lastName: String\n    let phoneNumber: String\n    \n    init(firstName: String, lastName: String, phoneNumber: String) {\n        self.firstName = firstName\n        self.lastName = lastName\n        self.phoneNumber = phoneNumber\n    }\n    \n    \/\/ Decode\n    required init(from decoder: Decoder) throws {\n        let container = try decoder.container(keyedBy: CodingKeys.self)\n        self.firstName = try container.decode(String.self, forKey: .firstName)\n        self.lastName = try container.decode(String.self, forKey: .lastName)\n        self.phoneNumber = try container.decode(String.self, forKey: .phoneNumber) \n        \/\/ See alternative below\n        \n        \/\/ If there are possibilities that a field contains NULL,\n        \/\/then the following code can be used (in this case instead of above)\n        if let phoneNumber =  try container.decodeIfPresent(String.self, forKey:            .phoneNumber) {\n                    self.phoneNumber = phoneNumber\n                }else {\n                    self.phoneNumber = &quot;&quot;\n                }\n        \/\/ End of alternative code\n    }\n    \n    \/\/Encode\n    func encode(to encoder: Encoder)  throws {\n        var container = encoder.container(keyedBy: CodingKeys.self)\n        try container.encode(firstName, forKey: .firstName)\n        try container.encode(lastName, forKey: .lastName)\n        try container.encode(phoneNumber, forKey: .phoneNumber)\n    } \n}\n\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">SwiftUI<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">import<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">SwiftData<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">@Model<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">class<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Persons<\/span><span style=\"color: #D4D4D4\">: Codable {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">enum<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">CodingKeys<\/span><span style=\"color: #D4D4D4\">: CodingKey {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">case<\/span><span style=\"color: #D4D4D4\"> firstName, lastName, phoneNumber<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">let<\/span><span style=\"color: #D4D4D4\"> firstName: <\/span><span style=\"color: #4EC9B0\">String<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">let<\/span><span style=\"color: #D4D4D4\"> lastName: <\/span><span style=\"color: #4EC9B0\">String<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">let<\/span><span style=\"color: #D4D4D4\"> phoneNumber: <\/span><span style=\"color: #4EC9B0\">String<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">init<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">firstName<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">lastName<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #DCDCAA\">phoneNumber<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">firstName<\/span><span style=\"color: #D4D4D4\"> = firstName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">lastName<\/span><span style=\"color: #D4D4D4\"> = lastName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\"> = phoneNumber<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ Decode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">required<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">init<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">from<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">decoder<\/span><span style=\"color: #D4D4D4\">: Decoder) <\/span><span style=\"color: #C586C0\">throws<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">let<\/span><span style=\"color: #D4D4D4\"> container = <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> decoder.<\/span><span style=\"color: #DCDCAA\">container<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">keyedBy<\/span><span style=\"color: #D4D4D4\">: CodingKeys.self)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">firstName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">decode<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">.self, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">firstName<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">lastName<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">decode<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">.self, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">lastName<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">decode<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">.self, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\">) <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ See alternative below<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ If there are possibilities that a field contains NULL,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/then the following code can be used (in this case instead of above)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">let<\/span><span style=\"color: #D4D4D4\"> phoneNumber =  <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">decodeIfPresent<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">String<\/span><span style=\"color: #D4D4D4\">.self, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">:            .<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\"> = phoneNumber<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><span style=\"color: #C586C0\">else<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #569CD6\">self<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #6A9955\">\/\/ End of alternative code<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/Encode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">func<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">encode<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">to<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">encoder<\/span><span style=\"color: #D4D4D4\">: Encoder)  <\/span><span style=\"color: #C586C0\">throws<\/span><span style=\"color: #D4D4D4\"> {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> container = encoder.<\/span><span style=\"color: #DCDCAA\">container<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">keyedBy<\/span><span style=\"color: #D4D4D4\">: CodingKeys.self)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">encode<\/span><span style=\"color: #D4D4D4\">(firstName, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">firstName<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">encode<\/span><span style=\"color: #D4D4D4\">(lastName, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">lastName<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">try<\/span><span style=\"color: #D4D4D4\"> container.<\/span><span style=\"color: #DCDCAA\">encode<\/span><span style=\"color: #D4D4D4\">(phoneNumber, <\/span><span style=\"color: #DCDCAA\">forKey<\/span><span style=\"color: #D4D4D4\">: .<\/span><span style=\"color: #9CDCFE\">phoneNumber<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    } <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>When moving from Core Data to Swift Data, it&#8217;s not obvious how to make the data model codable, a must for reading or writing JSON files or API&#8217;s to\/from the persistent storage. A way to do it is to manually add Codekeys so that the @Model knows that the data types are supported. Here is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-73","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"blocksy_meta":"","_links":{"self":[{"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/posts\/73","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/comments?post=73"}],"version-history":[{"count":1,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":75,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/posts\/73\/revisions\/75"}],"wp:attachment":[{"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/media?parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/categories?post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sekjell.com\/swift\/wp-json\/wp\/v2\/tags?post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}