{"id":241,"date":"2022-04-18T09:02:47","date_gmt":"2022-04-18T09:02:47","guid":{"rendered":"https:\/\/www.kindsonthegenius.com\/scala\/?p=241"},"modified":"2022-04-18T10:16:32","modified_gmt":"2022-04-18T10:16:32","slug":"scala-building-json-decoders-with-circe","status":"publish","type":"post","link":"https:\/\/www.kindsonthegenius.com\/scala\/scala-building-json-decoders-with-circe\/","title":{"rendered":"Scala &#8211; Building Json Decoders With Circe"},"content":{"rendered":"<p>In the previous two tutorials, we covers how to build Json encoders in Scala using Circe. You can review them here:<\/p>\n<ul class=\"display-posts-listing\">\n<li class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.kindsonthegenius.com\/scala\/scala-json-encoding-with-circe\/\">Scala \u2013 Json Encoding With Circe<\/a><\/li>\n<li class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.kindsonthegenius.com\/scala\/scala-build-json-encoder-with-circe\/\">Scala \u2013 Build Json Encoder With Circe<\/a><\/li>\n<\/ul>\n<p>In this tutorial, we would cover how to build Json Decoders in Scala using Circe. So let&#8217;s get started<\/p>\n<ol>\n<li><a href=\"#t1\">Create Some Author and Article Json Objects<\/a><\/li>\n<li><a href=\"#t2\">Building Decoders Using ProductN<\/a><\/li>\n<li><a href=\"#t3\">Using our Decoder to Decode<\/a><\/li>\n<li><a href=\"#t4\">Using DecodeAccumulating Function<\/a><\/li>\n<li><a href=\"#t5\">Using For Comprehension<\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t1\">1. Create some Author and Article Json<\/strong><\/h4>\n<p>Remember that a decoder is used to decode some Json value into a type. Now let&#8217;s create some Json values that we would be using to test the decode we&#8217;ll build.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Create two Author Json Objects, one valid and on inValid<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">val<\/span> validAuthor <span style=\"color: #008800; font-weight: bold;\">=<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"name\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"background-color: #fff0f0;\">\"Kindson\"<\/span><span style=\"color: #333333;\">.<\/span>asJson\r\n<span style=\"color: #333333;\">)<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">val<\/span> invalidAuthor <span style=\"color: #008800; font-weight: bold;\">=<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"name\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"color: #6600ee; font-weight: bold;\">45.<\/span>asJson\r\n<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Then we also create two more Json objects for article<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Create two Article objects<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">val<\/span> validArticle<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Json<\/span> <span style=\"color: #333333;\">=<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"id\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span>  <span style=\"background-color: #fff0f0;\">\"5cc24c45-e692-45d5-8092-64c73d886abd\"<\/span><span style=\"color: #333333;\">.<\/span>asJson<span style=\"color: #333333;\">,<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"title\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"background-color: #fff0f0;\">\"Candle in the wind\"<\/span><span style=\"color: #333333;\">.<\/span>asJson<span style=\"color: #333333;\">,<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"content\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"background-color: #fff0f0;\">\"..\"<\/span><span style=\"color: #333333;\">.<\/span>asJson<span style=\"color: #333333;\">,<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"author\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n        <span style=\"background-color: #fff0f0;\">\"name\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"background-color: #fff0f0;\">\"John Munonye\"<\/span><span style=\"color: #333333;\">.<\/span>asJson\r\n    <span style=\"color: #333333;\">)<\/span>\r\n<span style=\"color: #333333;\">)<\/span>\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">val<\/span> inValidArticle<span style=\"color: #008800; font-weight: bold;\">:<\/span> <span style=\"color: #333399; font-weight: bold;\">Json<\/span> <span style=\"color: #333333;\">=<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"id\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span>  <span style=\"background-color: #fff0f0;\">\"5cc24c45-e692-45d5-8092-64c73d886abd\"<\/span><span style=\"color: #333333;\">.<\/span>asJson<span style=\"color: #333333;\">,<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"content\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span><span style=\"color: #6600ee; font-weight: bold;\">998.<\/span>asJson<span style=\"color: #333333;\">,<\/span>\r\n    <span style=\"background-color: #fff0f0;\">\"author\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Json<\/span><span style=\"color: #333333;\">.<\/span>obj<span style=\"color: #333333;\">(<\/span>\r\n        <span style=\"background-color: #fff0f0;\">\"name\"<\/span> <span style=\"color: #333333;\">-&gt;<\/span> <span style=\"background-color: #fff0f0;\">\"John Munonye\"<\/span><span style=\"color: #333333;\">.<\/span>asJson\r\n    <span style=\"color: #333333;\">)<\/span>\r\n<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t1\">2. Building Decoders Using forProduct<em>N<\/em><\/strong><\/h4>\n<p>The easiest way to define a decoder is the use the forProductN method of the decoder where N is the number of fields in the case class. This method take the two parameter lists as specified. The second parameter list expects a function that can build the Author instance out of the two arguments provided. This is the Apply method. The complete decoder is given below:<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Build an author decoder using the forProductN method of the Docoder<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> authorDecoder <span style=\"color: #008800; font-weight: bold;\">=<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Decoder<\/span><span style=\"color: #333333;\">.<\/span>forProduct2<span style=\"color: #333333;\">(<\/span><span style=\"background-color: #fff0f0;\">\"name\"<\/span><span style=\"color: #333333;\">,<\/span> <span style=\"background-color: #fff0f0;\">\"bio\"<\/span><span style=\"color: #333333;\">)(<\/span><span style=\"color: #bb0066; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">.<\/span>apply<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Decoders built in this way using the forProductN is known as <strong><em>applicative-based<\/em>\u00a0<em>decoders<\/em><\/strong> and it gives us the ability to accumulate errors. However, this limits our ability to model complex logic<\/p>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t3\">3. Using Our Decoder to Decode<\/strong><\/h4>\n<p>Given our decoder, we can convert our validAuthor into an instance of Author using one of two ways:<\/p>\n<p><strong>Method 1 &#8211; using hcursor<\/strong><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Perform decoding using the hcursor method<\/span>\r\nauthorDecoder<span style=\"color: #333333;\">(<\/span>validAuthor<span style=\"color: #333333;\">.<\/span>hcursor<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Method 2 &#8211; using as() method<\/strong><\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Perform decoding by calling the .as() method on the Json Object<\/span>\r\nvalidAuthor<span style=\"color: #333333;\">.<\/span>as<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">]<\/span>\r\n<\/pre>\n<p>This gives use a Decode Result which could either be a decode failure on the <em>Left<\/em>, or a valid author instance on the <em>Right<\/em><\/p>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t4\">4. Using Decode Accumulating Method<\/strong><\/h4>\n<p>The decodeAccumulating method can be used as well to perform decoding. The benefit of the decodeAccumulating method is that it can give a list of decoding failures indicates all the problems with the Json object.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Using the DecodeAccumulating method to perform decoding. This approach helps us accumulate errors<\/span>\r\nauthorDecoder<span style=\"color: #333333;\">.<\/span>decodeAccumulating<span style=\"color: #333333;\">(<\/span>invalidAuthor<span style=\"color: #333333;\">.<\/span>hcursor<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h4><strong id=\"t5\">5. Decoder for Article Using for() Comprehension<\/strong><\/h4>\n<p>We would create a function and in the body of that function, we would decode every field one by one and in the final yield we build an instance of Article.<\/p>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #888888;\">\/\/ Build an article decoder using the for comprehension<\/span>\r\n<span style=\"color: #008800; font-weight: bold;\">implicit<\/span> <span style=\"color: #008800; font-weight: bold;\">val<\/span> articleDecoder<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;\">Article<\/span><span style=\"color: #333333;\">]<\/span> <span style=\"color: #008800; font-weight: bold;\">=<\/span> json <span style=\"color: #008800; font-weight: bold;\">=&gt;<\/span>\r\n    <span style=\"color: #008800; font-weight: bold;\">for<\/span> <span style=\"color: #333333;\">{<\/span>\r\n        id <span style=\"color: #008800; font-weight: bold;\">&lt;-<\/span> json<span style=\"color: #333333;\">.<\/span>get<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">UUID<\/span><span style=\"color: #333333;\">](<\/span><span style=\"background-color: #fff0f0;\">\"id\"<\/span><span style=\"color: #333333;\">)<\/span>\r\n        title <span style=\"color: #008800; font-weight: bold;\">&lt;-<\/span> json<span style=\"color: #333333;\">.<\/span>get<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">](<\/span><span style=\"background-color: #fff0f0;\">\"title\"<\/span><span style=\"color: #333333;\">)<\/span>\r\n        content <span style=\"color: #008800; font-weight: bold;\">&lt;-<\/span> json<span style=\"color: #333333;\">.<\/span>get<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">String<\/span><span style=\"color: #333333;\">](<\/span><span style=\"background-color: #fff0f0;\">\"content\"<\/span><span style=\"color: #333333;\">)<\/span>\r\n        author <span style=\"color: #008800; font-weight: bold;\">&lt;-<\/span> json<span style=\"color: #333333;\">.<\/span>get<span style=\"color: #333333;\">[<\/span><span style=\"color: #333399; font-weight: bold;\">Author<\/span><span style=\"color: #333333;\">](<\/span><span style=\"background-color: #fff0f0;\">\"author\"<\/span><span style=\"color: #333333;\">)<\/span>\r\n    <span style=\"color: #333333;\">}<\/span> <span style=\"color: #008800; font-weight: bold;\">yield<\/span> <span style=\"color: #bb0066; font-weight: bold;\">Article<\/span><span style=\"color: #333333;\">(<\/span>id<span style=\"color: #333333;\">,<\/span> title<span style=\"color: #333333;\">,<\/span> content<span style=\"color: #333333;\">,<\/span> author<span style=\"color: #333333;\">)<\/span>\r\n<\/pre>\n<p>Note that the direction of the arrows indicate that decoded field are assigned to variables. In the yield, we then build an Article instance using these variables that we obtained from decoding. This is called monadic decoders and it gives us the ability to model complex logic\u00a0 but we&#8217;ll not have error accumulation.<\/p>\n<p>In the same way we can decode the Article Json object using this new decoder. We can use either <strong><em>hcursor<\/em><\/strong> or <em><strong>as()<\/strong><\/em> method as earlier explained.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Exercise<\/strong><\/p>\n<p>Create a couple of invalid Json Articles and try to decode them<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous two tutorials, we covers how to build Json encoders in Scala using Circe. You can review them here: Scala \u2013 Json Encoding &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,45],"class_list":["post-241","post","type-post","status-publish","format-standard","hentry","category-scala-programming","tag-circe","tag-json-decoder"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/241","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=241"}],"version-history":[{"count":4,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/241\/revisions"}],"predecessor-version":[{"id":245,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/posts\/241\/revisions\/245"}],"wp:attachment":[{"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/media?parent=241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/categories?post=241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kindsonthegenius.com\/scala\/wp-json\/wp\/v2\/tags?post=241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}