{"id":246,"date":"2022-04-18T14:51:51","date_gmt":"2022-04-18T14:51:51","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/scala\/?p=246"},"modified":"2022-04-18T14:51:51","modified_gmt":"2022-04-18T14:51:51","slug":"scala-automatic-derivation-of-encoders-and-decoders","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/scala\/scala-automatic-derivation-of-encoders-and-decoders\/","title":{"rendered":"Scala &#8211; Automatic Derivation of Encoders and Decoders"},"content":{"rendered":"<p>In the previous two tutorials, we learnt how to build encoders and decoders. We used the forProductN(applicative-based decoders) and for comprehension (monadic decoders) to build decoders.<\/p>\n<p>In this tutorial, we would talk about auto and semi-auto derivation of decoders. In this case, we would not have to write all the boiler-plate codes.<\/p>\n<ol>\n<li><a href=\"#t1\">Automatic Derivation of Encoders and Decoders<\/a><\/li>\n<li><a href=\"#t2\">Semi-Automatic Derivation<\/a><\/li>\n<li><a href=\"#t3\">Deriving Codecs<\/a><\/li>\n<li><a href=\"#t4\">Creating Custom Codec<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t1\">1. Automatic Derivation<\/strong><\/h4>\n<p>Automatic Derivation can be gotten from the implicit scope. To use it, you need to first add the following dependency to your build.sbt<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">libraryDependencies <span style=\"color: #333333;\">+=<\/span> <span style=\"background-color: #fff0f0;\">\"io.circe\"<\/span> <span style=\"color: #333333;\">%%<\/span> <span style=\"background-color: #fff0f0;\">\"circe-generic\"<\/span> <span style=\"color: #333333;\">%<\/span> <span style=\"background-color: #fff0f0;\">\"0.14.1\"<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Then you also need to import generic.auto from io.circe like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">import<\/span> <span style=\"color: #0e84b5; font-weight: bold;\">io.circe.generic.auto._<\/span>\r\n<\/pre>\n<p>Once we do this, circe would derive for us encoders and decoders for any case class whose fields also has encoders and decoders. This also works with nested case classes as well.<\/p>\n<p>So assuming we have the following classes just like before:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/The Author case class<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">case<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">(<\/span>\r\n                   name<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">,<\/span>\r\n                   bio<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Option<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">]<\/span>\r\n                 <span style=\"color: #333333;\">)<\/span>\r\n\r\n<span style=\"color: #888888;\">\/\/The Article case class<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">case<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Article<\/span><span style=\"color: #333333;\">(<\/span>\r\n                    id<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">UUID<\/span><span style=\"color: #333333;\">,<\/span>\r\n                    title<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">,<\/span>\r\n                    content<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">,<\/span>\r\n                    author<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Author<\/span>\r\n                  <span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Then we can simply have all the encoders and decoders from the implicit scope like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\">implicitly<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Encoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">]]<\/span>\r\nimplicitly<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Decoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">]]<\/span>\r\n\r\nimplicitly<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Encoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Article<\/span><span style=\"color: #333333;\">]]<\/span>\r\nimplicitly<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Decoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Article<\/span><span style=\"color: #333333;\">]]<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Then we can just encode and decode as usual using the encoders and decoders.<\/p>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t2\">2. Semi-Automatic Derivation<\/strong><\/h4>\n<p>Semi-Automatic derivation uses macros to provide you with encoders and decoders for your type without having to write them manually. However, it requires you to ask for Codec explicitly for any type you want to work with.<\/p>\n<p>The import is:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">import<\/span> <span style=\"color: #0e84b5; font-weight: bold;\">io.circe.generic.semiauto._<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>With this, if you want to have a user class for instance<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">case<\/span> <span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">(<\/span>\r\n               firstName<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">,<\/span>\r\n               lastname<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">,<\/span>\r\n               email<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">String<\/span>\r\n               <span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>We can then ask for encoder and decoder for the User type like so:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/Request for encoder and decoder for the Person type<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> personDecoder<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Decoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span> <span style=\"color: #008800; font-weight: bold;\">=<\/span> deriveDecoder<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> personEncoder<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Encoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span>  <span style=\"color: #008800; font-weight: bold;\">=<\/span> deriveEncoder<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t3\">3. Deriving Codecs<\/strong><\/h4>\n<p>You can also derive a Codec, which is a combination of Encoder and Decoder in a single structure. You can create a codec for Person using the line below:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> personCodec<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Codec<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span> <span style=\"color: #008800; font-weight: bold;\">=<\/span> deriveCodec<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Person<\/span><span style=\"color: #333333;\">]<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t4\">4. Custom Codecs<\/strong><\/h4>\n<p>We want to build an encoder for case classes User and YouTubeVideo. The YouTubeVideo class is a wrapper class around single property, video id. The User is a class with two properties: name and YouTubeVideo.<\/p>\n<p>What we want to achieve is to serialise the User class such that the output would give name and an video url (built from the video id like http:\/\/yoube.com\/watch?v={videoId}.<\/p>\n<p>The code below shows an Encoder that modifies the value of one of the fields<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">object<\/span> <span style=\"color: #bb0066; font-weight: bold;\">MyCodec<\/span> <span style=\"color: #333333;\">{<\/span>\r\n  \r\n  <span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> videoEncoder<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Encoder<\/span><span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">YoutubeVideo<\/span><span style=\"color: #333333;\">]<\/span> <span style=\"color: #008800; font-weight: bold;\">=<\/span> video <span style=\"color: #008800; font-weight: bold;\">=&gt;<\/span>\r\n    <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>fromString<span style=\"color: #333333;\">(<\/span>s<span style=\"background-color: #fff0f0;\">\"http:\/\/www.youtube.com\/watch?v=${video.id}\"<\/span><span style=\"color: #333333;\">)<\/span>\r\n\r\n<span style=\"color: #333333;\">}<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous two tutorials, we learnt how to build encoders and decoders. We used the forProductN(applicative-based decoders) and for comprehension (monadic decoders) to build &hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[41,46,44,43],"class_list":["post-246","post","type-post","status-publish","format-standard","hentry","category-scala-programming","tag-circe","tag-codec","tag-decoder","tag-encoder"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/comments?post=246"}],"version-history":[{"count":3,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/246\/revisions"}],"predecessor-version":[{"id":252,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/246\/revisions\/252"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/media?parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/categories?post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/tags?post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}