<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jackson Archives - Codersee blog- Kotlin on the backend</title>
	<atom:link href="https://blog.codersee.com/tag/jackson/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Kotlin &#38; Backend Tutorials - Learn Through Practice.</description>
	<lastBuildDate>Wed, 16 Apr 2025 04:50:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.codersee.com/wp-content/uploads/2025/04/cropped-codersee_logo_circle_2-32x32.png</url>
	<title>Jackson Archives - Codersee blog- Kotlin on the backend</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Retrofit With Kotlin Coroutines: What You Need To Know</title>
		<link>https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/</link>
					<comments>https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 08 Nov 2022 06:30:52 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Jackson]]></category>
		<category><![CDATA[Retrofit]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=5503837</guid>

					<description><![CDATA[<p>In this ultimate guide, I will show you how to use Retrofit 2 With Kotlin Coroutines and what exactly you should know to use it. </p>
<p>The post <a href="https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/">Retrofit With Kotlin Coroutines: What You Need To Know</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2 class="article-heading-introduction">1. Introduction</h2>
<p>Hello! In this article, I would like to show you how to use <strong>Retrofit 2</strong> with <strong>Kotlin coroutines</strong>.</p>
<p>Please keep in mind, that this blog post is a continuation of the <a href="https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/">previous ultimate retrofit guide</a> and we will focus on how to adjust the project to work properly with Kotlin coroutines. If you haven&#8217;t seen it yet, then you should definitely do that before heading to this one.</p>
<p>Either way, I can assure you that <strong>after finishing these two tutorials, you will have a full understanding of Retrofit and its features</strong>.</p>
<blockquote><p>I&#8217;ve created this article as a response to Uduak comment- thank you for your feedback and I&#8217;m always happy to chat with you all 🙂</p></blockquote>
<p>Finally, please keep in mind that the official support for coroutines has been added in Retrofit2 version <a href="https://github.com/square/retrofit/blob/master/CHANGELOG.md#version-260-2019-06-05" target="_blank" rel="noopener">2.6.0</a>.</p>
<h2 class="article-heading-introduction">2. Retrofit Kotlin Coroutines Imports</h2>
<p>As the first step, we have to add coroutines functionality to our existing project.</p>
<p>To do so, we will use the <strong>kotlinx-coroutines-core</strong>. And to be on the same page, I will be using the version: <strong>1.6.4.</strong><br />
&nbsp;</p>
<p><a href="https://codersee.com/newsletter/"><img fetchpriority="high" decoding="async" class="aligncenter wp-image-3002956 size-large" src="http://blog.codersee.com/wp-content/uploads/2022/05/join_newsletter-1024x576.png" alt="Image shows two ebooks people can get for free after joining newsletter" width="800" height="419" /></a></p>
<p>&nbsp;</p>
<h3 class="article-heading-sub">2.1. Maven</h3>
<p>If you are working with Maven, then you can add it to your project with the following lines:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw">&lt;dependency&gt;
  &lt;groupId&gt;org.jetbrains.kotlinx&lt;/groupId&gt;
  &lt;artifactId&gt;kotlinx-coroutines-core&lt;/artifactId&gt;
  &lt;version&gt;(VERSION)&lt;/version&gt;
&lt;/dependency&gt;</pre>
<h3 class="article-heading-sub">2.2. Gradle</h3>
<p>Alternatively, we can use Gradle to fetch the library:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw">// build.gradle
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:&lt;VERSION&gt;'
// build.gradle.kts
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:&lt;VERSION&gt;")</pre>
<h2 class="article-heading-introduction">3. Edit UserApi</h2>
<p>Nextly, let&#8217;s navigate to the <strong>UserApi</strong> interface and make the necessary changes.</p>
<p>Please keep in mind, that the changes I&#8217;m gonna cover here can be applied to each function inside the UserApi (but to avoid boilerplate, I&#8217;ll focus on the GET function):</p>
<blockquote><p>Note: as always, you can find the link to GitHub repository with all examples in the end of this article 🙂</p></blockquote>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">interface UserApi {
  @GET("users")
  suspend fun getUsers(): Response&lt;List&lt;User&gt;&gt;
}</pre>
<p>As we can see, only two adjustments are necessary here:</p>
<ul>
<li>add <strong>suspend</strong> modifier- which in the coroutine&#8217;s context means that our function can be <em>suspended</em> (paused) and <em>resumed</em> (without blocking),</li>
<li>replace a <strong>Call</strong> with a <strong>Response </strong>&#8211; per the release notes, underneath it behaves just like <code class="EnlighterJSRAW" data-enlighter-language="kotlin">fun getUsers(): Response&lt;List&lt;User&gt;&gt;</code> invoked with <code class="EnlighterJSRAW" data-enlighter-language="generic">Call.enqueue</code>.</li>
</ul>
<p>Of course, if we are not interested in headers and status codes, then we can simply return the <strong>List of users</strong>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">interface UserApi {
  @GET("users")
  suspend fun getUsers(): List&lt;User&gt;
}</pre>
<h2 class="article-heading-introduction">4. Retrofit Client and Interceptors</h2>
<p>When it comes to the Retrofit client with Kotlin coroutines- we can keep it as it is:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">object RetrofitClient {

  // Base URL must end in /
  private const val BASE_URL = "http://localhost:8090/v1/"

  private val okHttpClient = OkHttpClient()
    .newBuilder()
    .addInterceptor(AuthorizationInterceptor)
    .addInterceptor(RequestInterceptor)
    .build()

  fun getClient(): Retrofit =
    Retrofit.Builder()
      .client(okHttpClient)
      .baseUrl(BASE_URL)
      .addConverterFactory(JacksonConverterFactory.create())
      .build()
}

object RequestInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    println("Outgoing request to ${request.url()}")
    return chain.proceed(request)
  }
}

object AuthorizationInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
    val requestWithHeader = chain.request()
      .newBuilder()
      .header(
        "Authorization", UUID.randomUUID().toString()
      ).build()
    return chain.proceed(requestWithHeader)
  }
}</pre>
<h2 class="article-heading-introduction">5. Retrofit User Service</h2>
<p>On the other hand, we need to make small adjustments to the <strong>UserService</strong> class:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">class UserService {

  private val retrofit = RetrofitClient.getClient()
  private val userApi = retrofit.create(UserApi::class.java)

  suspend fun successfulUsersResponse() {
    val usersResponse = userApi.getUsers()

    val successful = usersResponse.isSuccessful
    val httpStatusCode = usersResponse.code()
    val httpStatusMessage = usersResponse.message()

    val body: List&lt;User&gt;? = usersResponse.body()

  }

  suspend fun errorUsersResponse() {
    val usersResponse = userApi.getUsers()

    val errorBody: ResponseBody? = usersResponse.errorBody()

    val mapper = ObjectMapper()
    val mappedBody: ErrorResponse? = errorBody?.let { notNullErrorBody -&gt;
      mapper.readValue(notNullErrorBody.string(), ErrorResponse::class.java)
    }
  }

  suspend fun headersUsersResponse() {
    val usersResponse = userApi.getUsers()

    val headers = usersResponse.headers()
    val customHeaderValue = headers["custom-header"]
  }
}</pre>
<p>As we can see, we don&#8217;t have to invoke the <code class="EnlighterJSRAW" data-enlighter-language="generic">execute()</code> method anymore. In addition, we must mark functions with <code class="EnlighterJSRAW" data-enlighter-language="raw">suspend</code>&#8211; because the <code class="EnlighterJSRAW" data-enlighter-language="generic">getUsers()</code> can be either called only from a coroutine or another suspend function.</p>
<p>Finally, if we want to read the error body, we have to make use of the <code class="EnlighterJSRAW" data-enlighter-language="generic">string()</code> method, instead of <code class="EnlighterJSRAW" data-enlighter-language="generic">toString().</code> As the name suggests, this one returns the response as a String. When we run the <code class="EnlighterJSRAW" data-enlighter-language="generic">toString(),</code> we will eventually end up with a runtime exception.</p>
<h2 class="article-heading-introduction">6. Test Retrofit With Kotlin Coroutines</h2>
<p>As the last step, let&#8217;s <strong>test</strong> our Retrofit 2 functionality with Kotlin coroutines.</p>
<p>Although most probably, you will incorporate it into your Android project, to keep this blog post universal, I&#8217;ve prepared a simple <code class="EnlighterJSRAW" data-enlighter-language="generic">main()</code> function:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">fun main() = runBlocking {
  val service = UserService()

  coroutineScope {
    launch(Dispatchers.IO) {
      delay(10_000)

      println("[${Thread.currentThread().name}] One")

      service.successfulUsersResponse()
    }
    launch(Dispatchers.IO) {
      println("[${Thread.currentThread().name}] Two")

      service.successfulUsersResponse()
    }
  }

  println("[${Thread.currentThread().name}] Done!")
}</pre>
<p>If we run our program, we should see the following:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw">[DefaultDispatcher-worker-3] Two

# 10 seconds of delay

[DefaultDispatcher-worker-3] One

[main] Done!</pre>
<p>As we can clearly see, everything is working as expected.</p>
<h2 class="article-heading-introduction">7. Retrofit With Kotlin Coroutines Summary</h2>
<p>And that would be all for this blog post about <strong>Retrofit 2 with Kotlin coroutines</strong>.</p>
<p>As always, the source code for this article can be found in <a href="https://github.com/codersee-blog/kotlin-coroutines-retrofit-2" target="_blank" rel="noopener">this GitHub repository</a>.</p>
<p>Finally, if you enjoyed this content, or would like to ask me about anything, please let me know in the comments section below 🙂</p>
<p>The post <a href="https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/">Retrofit With Kotlin Coroutines: What You Need To Know</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>@JsonView With Spring Boot and Kotlin</title>
		<link>https://blog.codersee.com/jsonview-with-spring-boot-and-kotlin/</link>
					<comments>https://blog.codersee.com/jsonview-with-spring-boot-and-kotlin/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Mon, 01 Aug 2022 05:00:59 +0000</pubDate>
				<category><![CDATA[Spring]]></category>
		<category><![CDATA[Jackson]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=3003040</guid>

					<description><![CDATA[<p>In this article, we will take a look at the Jackson @JsonView annotation and how can we use it when working with Spring Boot and Kotlin.</p>
<p>The post <a href="https://blog.codersee.com/jsonview-with-spring-boot-and-kotlin/">@JsonView With Spring Boot and Kotlin</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2 class="article-heading-introduction">1. Introduction</h2>
<p>In this article, I would like to show you the Jackson <strong>@JsonView</strong> annotation and how to use it, when working <strong>Spring Boot and Kotlin</strong>.</p>
<p><strong>@JsonView</strong> is an annotation used to instruct the Jackson mapper, whether the annotated field is a part of the view and should be serialized, or not. And I know, it might sound a bit complicated, but in the next few minutes, I will prove that it is only a first impression.</p>
<h2 class="article-heading-introduction">2. Prepare Spring Boot Project</h2>
<h3 class="article-heading-introduction">2.1. Setup</h3>
<p>But before we dive into the @JsonView, let&#8217;s configure our sandbox Spring Boot project first. As always, I highly encourage you to use the <a href="https://start.spring.io/" target="_blank" rel="noopener">Spring Initializr page</a> to do it. Just to be on the same page, I am using the following settings:</p>
<ul>
<li><strong>Language:</strong> Kotlin</li>
<li><strong>Spring Boot version:</strong> 2.7.2</li>
<li><strong>Java:</strong> 17</li>
<li><strong>Dependencies:</strong> Spring Web</li>
<li><strong>Jackson version:</strong> 2.13.3</li>
</ul>
<p>Moreover, you can find the link to the repository with all examples in the Summary section for this article.</p>
<h3 class="article-heading-introduction">2.2. Prepare DTO</h3>
<p>With that being done, let&#8217;s create a data class called <code class="EnlighterJSRAW" data-enlighter-language="kotlin">ArticleDto</code>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">data class ArticleDto(
  val id: Long,
  val title: String,
  val category: String,
  val content: String,
  val views: Long,
  val likes: Long
)</pre>
<p>As we can see, this class is responsible for transferring the data about an article on a blog.</p>
<h3 class="article-heading-introduction">2.2. Implement Controller Class</h3>
<p>Following, let&#8217;s introduce the <code class="EnlighterJSRAW" data-enlighter-language="raw">ArticleController</code> to our codebase:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">@RestController
@RequestMapping("/articles")
class ArticleController {

  private val articles = mapOf(
    1L to ArticleDto(
      1L, "Article 1", "Spring Framework",
      "Content 1", 1000, 30
    ),
    2L to ArticleDto(
      2L, "Article 2", "Kotlin",
      "Content 2", 5000, 54
    )
  )

  @GetMapping
  fun getAllArticles(): List&lt;ArticleDto&gt; =
    articles.values.toList()

  @GetMapping("/{id}")
  fun getArticleDetails(@PathVariable id: Long): ArticleDto? =
    articles[id]

  @GetMapping("/{id}/analytics")
  fun getArticleAnalytics(@PathVariable id: Long): ArticleDto? =
    articles[id]
}</pre>
<p>As can be seen, in our example, we exposed 3 different endpoints:</p>
<ul>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles</code> &#8211; used to populate the list of articles</li>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}</code> &#8211; to obtain the details of an article by its identifier</li>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}/analytics</code> &#8211; to obtain the analytics data</li>
</ul>
<h3 class="article-heading-introduction">2.3. Check Endpoints</h3>
<p>With that being done, let&#8217;s quickly check how our Spring Boot app behaves without @JsonView.</p>
<p>Let&#8217;s query the /articles endpoint:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw">#Result: 

[
  {
    "id": 1,
    "title": "Article 1",
    "category": "Spring Framework",
    "content": "Content 1",
    "views": 1000,
    "likes": 30
  },
  {
    "id": 2,
    "title": "Article 2",
    "category": "Kotlin",
    "content": "Content 2",
    "views": 5000,
    "likes": 54
  }
]</pre>
<p>Everything is working fine and as a result, we receive a list of our test data.</p>
<p>On the other hand, when we query either the <code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}</code>, or the <code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}/analytics</code>, we see the following:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw">#Result: 

{
  "id": 1,
  "title": "Article 1",
  "category": "Spring Framework",
  "content": "Content 1",
  "views": 1000,
  "likes": 30
}</pre>
<p>At this point, both endpoints work in the same manner, but we will see how to change it in the next chapters.<br />
&nbsp;</p>
<p><a href="https://codersee.com/newsletter/"><img decoding="async" class="aligncenter wp-image-3002956 size-large" src="http://blog.codersee.com/wp-content/uploads/2022/05/join_newsletter-1024x576.png" alt="Image shows two ebooks people can get for free after joining newsletter" width="800" height="419" /></a></p>
<p>&nbsp;</p>
<h2 class="article-heading-introduction">3. How Does the @JsonView Help Me In Spring Boot Then?</h2>
<p>So, as I mentioned earlier- these 3 endpoints were created to return the data about <strong>all articles</strong>, <strong>details of the article</strong>, and <strong>analytics</strong>.</p>
<p>As we can clearly see, although they are working, we don&#8217;t need all of the data every time and we should limit the response payload:</p>
<ul>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles</code> &#8211; in the case of the list, the information about identifier, title, and category should be sufficient</li>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}</code> &#8211; when querying the details, we would like to get all the information</li>
<li><code class="EnlighterJSRAW" data-enlighter-language="raw">/articles/{id}/analytics</code> &#8211; we would like to use this one to obtain the views and likes information only</li>
</ul>
<p>Knowing these requirements we could introduce 3 different DTOs and implement appropriate mappers. Although this solution will work, managing multiple DTOs and mappers may become troublesome at some point. Additionally, in case of any change, we will have to mimic it across each one.</p>
<p>Nevertheless, the @JsonView is a great answer to this problem and in the next chapters, I will show you how to introduce it to our Spring Boot app.</p>
<h2 class="article-heading-introduction">4. Simple @JsonView</h2>
<p>With all of that being said, we can finally start working with the @JsonView.</p>
<p>As the first step, let&#8217;s create a new <code class="EnlighterJSRAW" data-enlighter-language="raw">Views</code> class with two inner interfaces:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">class Views {
  interface List
  interface Analytics
}</pre>
<p>Nextly, let&#8217;s modify our DTO a bit:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">data class ArticleDto(
  @field:JsonView(Views.List::class)
  val id: Long,
  @field:JsonView(Views.List::class)
  val title: String,
  @field:JsonView(Views.List::class)
  val category: String,
  val content: String,
  @field:JsonView(Views.Analytics::class)
  val views: Long,
  @field:JsonView(Views.Analytics::class)
  val likes: Long
)</pre>
<p>As we can see, the id, title, and category fields are a part of the List view. On the other hand, the views and likes properties belong to Analytics. If we test our endpoints now, we might be surprised that nothing changed, but <strong>that&#8217;s the desired state</strong>.</p>
<p><strong>To make use of the @JsonView in Spring Boot, we have to annotate our endpoints</strong>, as well:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">@GetMapping
@JsonView(Views.List::class)
fun getAllArticles(): List&lt;ArticleDto&gt; =
  articles.values.toList()

@JsonView(Views.Analytics::class)
@GetMapping("/{id}/analytics")
fun getArticleAnalytics(@PathVariable id: Long): ArticleDto? =
  articles[id]</pre>
<p>With that being done, let&#8217;s test these two endpoints once again:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw"># List view result: 

[
  {
    "id": 1,
    "title": "Article 1",
    "category": "Spring Framework"
  },
  {
    "id": 2,
    "title": "Article 2",
    "category": "Kotlin"
  }
]

# Analytics view result: 

{
  "views": 1000,
  "likes": 30
}</pre>
<p>And this time, response payloads are limited to the desired fields only. We don&#8217;t have to test the details endpoint, because we already know that <strong>nothing changes unless we mark the endpoint with @JsonView annotation</strong>.</p>
<h2 class="article-heading-introduction">5. Default View Inclusion</h2>
<p>As the next step, let&#8217;s take a second to understand the default view inclusion concept.</p>
<p>To do so, let&#8217;s add a <code class="EnlighterJSRAW" data-enlighter-language="raw">Config</code> class to our project:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">@Configuration
class Config {

  @Bean
  fun objectMapper(): ObjectMapper =
    JsonMapper.builder()
      .enable(MapperFeature.DEFAULT_VIEW_INCLUSION) //don't needed here, enabled by default
      .build()

}</pre>
<p>If we specify our bean explicitly, the <strong>DEFAULT_VIEW_INCLUSION feature will be enabled by default</strong>.</p>
<p>This means, that <strong>fields not annotated with @JsonView, will be still serialized</strong>. To better visualize it, let&#8217;s re-test our endpoints:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw"># List view result: 

[
  {
    "id": 1,
    "title": "Article 1",
    "category": "Spring Framework",
    "content": "Content 1"
  },
  {
    "id": 2,
    "title": "Article 2",
    "category": "Kotlin",
    "content": "Content 2"
  }
]

# Analytics view result: 

{
  "content": "Content 1",
  "views": 1000,
  "likes": 30
}</pre>
<p>As we can see, in both cases non-annotated <code class="EnlighterJSRAW" data-enlighter-language="raw">content</code> field is returned. Sometimes this behavior might be useful, but in some cases, it might cause us trouble, so we have to be aware of this behavior.</p>
<h2 class="article-heading-introduction">6. Extending Views</h2>
<p>As the last thing, let&#8217;s see another great feature- extending views.</p>
<p>Let&#8217;s imagine that we would like to introduce a new endpoint, which will return fields of both <strong>List</strong> and <strong>Analytics</strong> views. Let&#8217;s call it <strong>ListAndAnalytics</strong>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">class Views {
  interface List
  interface Analytics
  interface ListAndAnalytics
}</pre>
<p>As the next step, we could add our new view everywhere, where <code class="EnlighterJSRAW" data-enlighter-language="raw">List</code> or <code class="EnlighterJSRAW" data-enlighter-language="raw">Analytics</code> is presented:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">data class ArticleDto(
  @field:JsonView(Views.List::class, Views.ListAndAnalytics::class)
  val id: Long,
  @field:JsonView(Views.List::class, Views.ListAndAnalytics::class)
  val title: String,
  @field:JsonView(Views.List::class, Views.ListAndAnalytics::class)
  val category: String,
  val content: String,
  @field:JsonView(Views.Analytics::class, Views.ListAndAnalytics::class)
  val views: Long,
  @field:JsonView(Views.Analytics::class, Views.ListAndAnalytics::class)
  val likes: Long
)</pre>
<p>And although this works, the code becomes much less readable. (and imagine what will happen if we decide to add even more views)</p>
<p>We can simply avoid that by making our new interface extending the two others:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">class Views {
  interface List
  interface Analytics
  interface ListAndAnalytics : List, Analytics
}</pre>
<p>And annotate our endpoint appropriately:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">@JsonView(Views.ListAndAnalytics::class)
@GetMapping("/{id}/list-and-analytics")
fun getArticleListAndAnalytics(@PathVariable id: Long): ArticleDto? =
  articles[id]</pre>
<p>Which, when queried, will produce the following result:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="raw"># List and analytics view result: 

{
  "id": 1,
  "title": "Article 1",
  "category": "Spring Framework",
  "views": 1000,
  "likes": 30
}</pre>
<p>As we can see, with this simple approach we can easily create a hierarchy of views in our codebase.</p>
<h2 class="article-heading-introduction">5. @JsonView with Spring Boot Summary</h2>
<p>And that would be all for this article on what the <strong>@JsonView</strong> annotation brings to the table when working with <strong>Spring Boot</strong>. I hope that after reading this tutorial you will be able to apply it to your code and save your precious time during the development</p>
<blockquote><p>Pssst&#8230; if you would like to contribute to Codersee and <strong>support the creation of content, you can &#8220;<a href="https://ko-fi.com/codersee" target="_blank" rel="noopener">buy me a coffee</a>&#8220;</strong>. Have a great day! 🙂</p></blockquote>
<p>Also, you can find the source code with examples in <a href="https://github.com/codersee-blog/jsonview-spring-boot-kotlin" target="_blank" rel="noopener">this GitHub repository</a> (and other articles related to Jackson on my blog <a href="https://blog.codersee.com/tag/jackson/">right here</a>).</p>
<p>The post <a href="https://blog.codersee.com/jsonview-with-spring-boot-and-kotlin/">@JsonView With Spring Boot and Kotlin</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/jsonview-with-spring-boot-and-kotlin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>@JsonProperty vs @JsonAlias in Jackson</title>
		<link>https://blog.codersee.com/jsonproperty-vs-jsonalias-jackson/</link>
					<comments>https://blog.codersee.com/jsonproperty-vs-jsonalias-jackson/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Mon, 25 Jul 2022 05:30:45 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Jackson]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=3003004</guid>

					<description><![CDATA[<p>This time, I would like to show you a @JsonProperty vs @JsonAlias Jackson annotation comparison and a few things worth remembering.</p>
<p>The post <a href="https://blog.codersee.com/jsonproperty-vs-jsonalias-jackson/">@JsonProperty vs @JsonAlias in Jackson</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-1-introduction">1. Introduction</h2>



<p>Hello friend, in this article I would like to show you a <strong>@JsonProperty</strong> vs <strong>@JsonAlias</strong> Jackson annotations comparison.</p>



<p>Together, we will see what exactly these two annotations are and how to use them properly in our, not only Spring Boot projects. As always, we will use the Kotlin programming language, but the things you&#8217;re gonna learn today can be easily incorporated into Java projects, as well.</p>



<h2 class="wp-block-heading" id="h-3-serialization-vs-deserialization">3. Serialization vs Deserialization</h2>



<p>Nevertheless, before we dive into the @JsonProperty vs @JsonAlias topic, let&#8217;s take a second to distinguish these two terms:</p>



<ul class="wp-block-list">
<li><strong>serialization</strong>&#8211; is a process of converting an object existing in memory into a stream of bytes, so that it can be stored, or transmitted. In our case, converting Kotlin/Java objects into JSON is an example of serialization</li>



<li><strong>deserialization</strong>&#8211; this is the reverse process, in which a stream of bytes (ex. JSON) is converted to an object existing in memory</li>
</ul>


<p>[elementor-template id=&#8221;9007393&#8243;]</p>



<h2 class="wp-block-heading" id="h-2-jsonproperty">2. @JsonProperty</h2>



<h3 class="wp-block-heading" id="h-2-1-definition-and-defaults">2.1. Definition And Defaults</h3>



<p>With that being said, let&#8217;s answer the question- what exactly the <strong>@JsonProperty</strong> annotation is?</p>



<p>In Jackson, it is a marker annotation, which can be used to mark non-static methods and fields as a logical property. Simply put, we use it to tell Jackson&#8217;s ObjectMapper to map a given JSON field to a particular object field.</p>



<p>By default, <strong>the field name is used as a property name</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
    @JsonProperty val id: Long,
    @JsonProperty val name: String
)
</pre>



<p>As we can see, our example DTO consists of two fields, which when populated with some random data, will be translated to the given JSON:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr"
}
</pre>



<p>Of course, the above structure will be the same for both serialization and deserialization.</p>



<p>Moreover, if we would leave the above data class without any annotation, the result would be exactly the same.</p>



<h3 class="wp-block-heading" id="h-2-2-so-what-do-i-need-jsonproperty-for">2.2. So What Do I Need @JsonProperty For?</h3>



<p>Although you might think this annotation is useless after the previous sentence, let me walk you through a few use cases.</p>



<p>Definitely, the most popular one is changing the way, we would like the JSON to look. When we specify a non-empty value, then this value will be used:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
    @JsonProperty val id: Long,
    @JsonProperty("person_name") val personName: String
)
</pre>



<p>And this time, the JSON structure will look, as follows:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "person_name": "Piotr"
}
</pre>



<p>This way, a <strong>camel case</strong> used in our code is translated to the <strong>snake case</strong>, often used in REST APIs.</p>



<h3 class="wp-block-heading" id="h-2-3-different-structure-for-serialization-and-deserialization">2.3. Different Structure For Serialization And Deserialization</h3>



<p>As the next step, let&#8217;s see how we can keep JSONs used for serialization and deserialization completely different. Although my example will be a bit extreme, you may encounter a similar situation when working with some external APIs in your project.</p>



<p>Let&#8217;s imagine, that you would like to fetch some data from an external API and then forward them to the user querying your endpoint. To do so, you could either use two, separate data classes and perform mapping or simply make use of @JsonProperty possibilities:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  @JsonProperty("external_id")
  @get:JsonProperty("id_for_user")
  val id: Long,
  
  @JsonProperty("external_name")
  @get:JsonProperty("name_for_user")
  val name: String
)
</pre>



<p>As can be seen, we made use of the <code class="EnlighterJSRAW" data-enlighter-language="kotlin">@get</code>, which in Kotlin means that we want to apply the annotation to <strong>property getter</strong>.</p>



<p>After these modifications, we would be able to read JSON in the following form:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "external_id": 1,
  "external_name": "Piotr"
}
</pre>



<p>And forward it to the user in this form:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id_for_user": 1,
  "name_for_user": "Piotr"
}</pre>



<h3 class="wp-block-heading" id="h-2-4-jsonproperty-with-enums">2.4. @JsonProperty With Enums</h3>



<p>Another interesting feature of @JsonProperty is the possibility <strong>to use it with enums</strong>. However, it&#8217;s been added in <strong>Jackson 2.6</strong>, so you might want to check a version in your project.</p>



<p>Anyway, let&#8217;s see the example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">enum class SomeType {
  STANDARD, PREMIUM
}

data class ExampleDto(
  val id: Long,
  val name: String,
  val type: SomeType
)
</pre>



<p>With the above code, our objects will look, as follows:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr",
  "type": "PREMIUM"
}
</pre>



<p>However, if we would like to change the JSON form, then we can mark it, as well:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">enum class SomeType {
  @JsonProperty("Tier 1")
  STANDARD,
  @JsonProperty("Tier 2")
  PREMIUM
}
</pre>



<p>After this change, the provided value will be used:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr",
  "type": "Tier 2"
}
</pre>



<p>This strategy can be useful when we don&#8217;t necessarily want to show the implementation details to users.</p>



<h3 class="wp-block-heading" id="h-2-4-different-access-types">2.4. Different Access Types</h3>



<p>The last thing, I would like to cover before we will see the @JsonProperty vs @JsonAlias comparison are access types.</p>



<p>@JsonProperty lets us set an optional <code class="EnlighterJSRAW" data-enlighter-language="kotlin">access</code> property to change the way Jackson interprets visibility rules for a given field. Let&#8217;s have a look at each one of the 4 access types:</p>



<ul class="wp-block-list">
<li><strong>AUTO (default)</strong> &#8211; which means that visibility rules will be applied to determine a read/write access of the property.</li>
</ul>



<p>As always, let&#8217;s have a look at the example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  @JsonProperty val id: Long,
  @JsonProperty val name: String,
  @JsonProperty private val email: String
)
</pre>



<p>As we can see, the email property is private, which means, that an example object will be serialized into this form:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr"
}</pre>



<p>On the other hand, when we try to deserialize a JSON containing an email property, then it will be read successfully.</p>



<ul class="wp-block-list">
<li><strong>READ_WRITE</strong> &#8211; this means that property will be accessible for both serialization and deserialization regardless of the visibility rules.</li>
</ul>



<p>Let&#8217;s apply a small change to our DTO:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  @JsonProperty val id: Long,
  @JsonProperty val name: String,
  @JsonProperty(access = JsonProperty.Access.READ_WRITE) private val email: String
)
</pre>



<p>This time, the email can be both serialized and deserialized, even though it is private:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr",
  "email": "contact@codersee.com"
}</pre>



<ul class="wp-block-list">
<li><strong>READ_ONLY</strong> &#8211; when applied, a property can be read for serialization, but cannot be set during the deserialization.</li>
</ul>



<p>With that being said, let&#8217;s see another example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  @JsonProperty(access = JsonProperty.Access.READ_ONLY) val id: Long?,
  @JsonProperty val name: String
)
</pre>



<p>As can be seen, the id property has to be set as a nullable type, so that it won&#8217;t fail during the deserialization. The serialized object looks as follows:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Piotr"
}</pre>



<p>However, when we try to deserialize a JSON with the same payload, the id will be set to null. This access type can be used when we would like to autogenerate id on the backend side and ignore user input.</p>



<ul class="wp-block-list">
<li><strong>WRITE_ONLY</strong> &#8211; with this one, the property can be set during the deserialization, but cannot be set during the serialization.</li>
</ul>



<p>And again, let&#8217;s see it in action:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) val id: Long,
  @JsonProperty val name: String
)
</pre>



<p>This time, the serialized object will have the following form:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "name": "Piotr"
}</pre>



<p>Additionally, we still have the possibility to pass an id property, which will be correctly read to an object.</p>



<h2 class="wp-block-heading" id="h-3-jsonalias">3. @JsonAlias</h2>



<p>With all of the above being said, let&#8217;s finally see what exactly <strong>@JsonAlias</strong> is? Since Jackson 2.9, this annotation lets us <strong>specify one, or more alternative names accepted during the deserialization</strong>.</p>



<p>So, for a given example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ExampleDto(
  val id: Long,
  @JsonAlias("n", "N", "surname")
  val name: String
)
</pre>



<p>The <code class="EnlighterJSRAW" data-enlighter-language="raw">name</code> value can be set from either <code class="EnlighterJSRAW" data-enlighter-language="raw">n</code>, <code class="EnlighterJSRAW" data-enlighter-language="raw">N</code>, <code class="EnlighterJSRAW" data-enlighter-language="raw">name</code>, or <code class="EnlighterJSRAW" data-enlighter-language="raw">surname</code> property.</p>



<p>If you are wondering now, which value will be chosen, when we specify more than one matching fields, just like here:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "surname": "Piotr",
  "N": "John"
}</pre>



<p>Then, the answer is- <strong>the last one</strong>.</p>



<p>Moreover, it can be used with enums, as well.</p>



<h2 class="wp-block-heading" id="h-4-jsonproperty-vs-jsonalias">4. @JsonProperty vs @JsonAlias</h2>



<p>Finally, let&#8217;s get back to the title of this post, the <strong>@JsonProperty vs @JsonAlias</strong> comparison.</p>



<p>Well, the most important thing to remember is that the @JsonAlias affects the <strong>deserialization process only</strong>. Nevertheless, it lets us specify multiple values. This makes it a great choice, when we want to reuse our DTO, or keep backward compatibility (for example, after the refactoring).</p>



<p>In my opinion, this annotation is a great addition to the @JsonProperty but should be used wisely. We don&#8217;t want any unwanted value to be set for our property 🙂</p>



<h2 class="wp-block-heading" id="h-5-summary">5. Summary</h2>



<p>And that would be all for this article on <strong>@JsonProperty vs @JsonAlias</strong>. If you&#8217;d like to learn a bit more or check out other annotations, then please refer to the <a href="https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-annotations/latest/index.html" target="_blank" rel="noopener">Jackson documentation</a>.</p>



<p>Let me know what are your favorite Jackson annotations. As always, you can do it in the comment section below, or by the <a href="https://codersee.com/contact/" target="_blank" rel="noopener">contact form</a>.</p>



<p>Finally, if you would like to contribute to Codersee and <strong>support the creation of content, you can &#8220;buy me a coffee&#8221; <a href="https://ko-fi.com/codersee" target="_blank" rel="noopener">right here</a>.</strong> Have a great day!</p>
<p>The post <a href="https://blog.codersee.com/jsonproperty-vs-jsonalias-jackson/">@JsonProperty vs @JsonAlias in Jackson</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/jsonproperty-vs-jsonalias-jackson/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>What Is The Difference Between Jackson NullNode and Null?</title>
		<link>https://blog.codersee.com/what-is-the-difference-between-jackson-nullnode-and-null/</link>
					<comments>https://blog.codersee.com/what-is-the-difference-between-jackson-nullnode-and-null/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 17 May 2022 10:07:10 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Jackson]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=2502834</guid>

					<description><![CDATA[<p>In this short article, I would like to explain the difference between the NullNode and null value when working with Jackson library.</p>
<p>The post <a href="https://blog.codersee.com/what-is-the-difference-between-jackson-nullnode-and-null/">What Is The Difference Between Jackson NullNode and Null?</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2 class="article-heading-introduction">1. Introduction</h2>
<p>In this short post, I would like to explain the difference between the <strong>NullNode</strong> and <strong>null</strong> value when working with Jackson library.</p>
<p>Although these two seem nearly exactly the same, we should be aware of the difference between them and apply appropriate handling in our codebase. Without this knowledge, we may introduce an unexpected behavior to application, which might be hard to track down later.</p>
<h2 class="article-heading-introduction">2. NullNode vs null value</h2>
<p>So without further ado, let&#8217;s clarify the difference between a <strong>NullNode</strong> and <strong>null</strong>:</p>
<ul>
<li><strong>the <a href="https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/latest/com/fasterxml/jackson/databind/node/NullNode.html" target="_blank" rel="noopener">NullNode</a></strong> is a singleton class used to contain an <strong>explicit JSON null value</strong></li>
<li><strong>null value</strong>, in terms of dealing with JsonNode, simply means that <strong> name/value pair does not exist for a given name</strong></li>
</ul>
<p>To better visualize this, let&#8217;s see the following example:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">val mapper = ObjectMapper()
val someObject = mapper.readTree("""
    {
        "id": 1,
        "age": null
    }
""")

val id = someObject.get("id")      // IntNode
val age = someObject.get("age")    // NullNode
val name = someObject.get("name")  // null</pre>
<p>As we can see, the <strong>age</strong> value set explicitly to null results in a <strong>NullNode instance </strong>being created. On the other hand, a missing <strong>name</strong> field will lead to a null value on get().</p>
<p>&nbsp;</p>
<p><a href="https://codersee.com/newsletter/"><img decoding="async" class="aligncenter wp-image-3002956 size-large" src="http://blog.codersee.com/wp-content/uploads/2022/05/join_newsletter-1024x576.png" alt="Image shows two ebooks people can get for free after joining newsletter" width="800" height="419" /></a></p>
<p>&nbsp;</p>
<h2 class="article-heading-introduction">3. Unexpected Behavior Example</h2>
<p>With that being said, let&#8217;s imagine that we are working with some external REST API in our application and we would like to perform some action based on whether the <strong>age</strong> is set for user. For the simplicity, we will print the age value to the output in our example.</p>
<p>Given these requirements, we&#8217;ve decided to simply check if the value is not null and based on that perform the action:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">val age = someObject.get("age")

if(age != null) {
    println("User age is set to $age")
}</pre>
<p>Alternatively, we&#8217;ve decided to make our Kotlin code even more Kotlin-like with <strong>let</strong>:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">someObject.get("age")
  ?.let { ageValue -&gt;
    println("User age is set to [$ageValue]")
  }</pre>
<p>As we can see, the above code will result in totally different behavior depending on whether the <strong>age</strong> property was set as null <strong>explicitly</strong>, or <strong>not</strong>.</p>
<p>To be even more specific, missing value won&#8217;t produce any output, whereas <code class="EnlighterJSRAW" data-enlighter-language="kotlin">"age" : null</code> will print <em>&#8220;User age is set to [null].&#8221;</em>.</p>
<h2 class="article-heading-introduction">4. Solution</h2>
<p>Although the above example is harmless, we should never let that happen and handle appropriately depending on our needs.</p>
<p>One of the possible ways to work with Nullnode and null value in Kotlin could be an additional type check:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">if(age != null &amp;&amp; age !is NullNode) {
    println("User age is set to $age")
}</pre>
<p>Although this is not the most beautiful solution, it makes our code insensitive to the way external API serialized age value.</p>
<p>Alternatively, Jackson library comes with plenty of handy methods, like <strong>isXYZ</strong> (example: <code class="EnlighterJSRAW" data-enlighter-language="kotlin">isBoolean()</code>, <code class="EnlighterJSRAW" data-enlighter-language="kotlin">isLong()</code>, <code class="EnlighterJSRAW" data-enlighter-language="kotlin">isNumber()</code> etc.):</p>
<pre class="EnlighterJSRAW" data-enlighter-language="kotlin">if (age.isNumber) {
    println("User age is set to $age")
}</pre>
<p>This way, we can make sure that our code will be invoked only if the node represents a numeric JSON value.</p>
<p>As I&#8217;ve mentioned above, <strong>JsonNode</strong> class comes with plenty of methods, which can help us to prevent our code from failure and I highly encourage you to check out the <a href="https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/latest/com/fasterxml/jackson/databind/JsonNode.html" target="_blank" rel="noopener">documentation</a>.</p>
<h2 class="article-heading-introduction">5. Summary</h2>
<p>And that would be all for this short article covering<strong> NullNode and null value differences in Jackson</strong>. I am more than sure, that this knowledge, will <span class="VIiyi" lang="en"><span class="JLqJ4b ChMk0b" data-language-for-alternatives="en" data-language-to-translate-into="pl" data-phrase-index="0" data-number-of-phrases="1"><span class="Q4iAWc"> keep you from making mistakes in the future.</span></span></span></p>
<p>Have you ever encountered similar &#8220;tricky&#8221; situations in your code with Jackson or any other library? If so, could you please share it with others in the comment section or by using a <a href="https://codersee.com/contact/" target="_blank" rel="noopener">contact form</a>?</p>
<p>Have a great week!</p>
<p>The post <a href="https://blog.codersee.com/what-is-the-difference-between-jackson-nullnode-and-null/">What Is The Difference Between Jackson NullNode and Null?</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/what-is-the-difference-between-jackson-nullnode-and-null/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Retrofit With Kotlin- The Ultimate Guide</title>
		<link>https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/</link>
					<comments>https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/#comments</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Mon, 28 Mar 2022 05:20:38 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Jackson]]></category>
		<category><![CDATA[Retrofit]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=2002671</guid>

					<description><![CDATA[<p>In this step by step guide I will show you Retrofit 2 features and how to configure it in a Kotlin project.</p>
<p>The post <a href="https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/">Retrofit With Kotlin- The Ultimate Guide</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading" id="h-1-introduction">1. Introduction</h2>



<p>This time, I would like to show you how to use <strong>Retrofit 2</strong> with <strong>Kotlin</strong>. I will walk you step by step through its features, capabilities and a few obstacles you may encounter when using it.</p>



<p>Let&#8217;s start by answering the question: what exactly the <a href="https://square.github.io/retrofit/" target="_blank" rel="noopener">Retrofit</a> is? It is a type-safe HTTP client for <strong>Android</strong> and <strong>Java</strong>. If you are looking for a library, which will help you to integrate external API in your mobile application, or a back-end service written in Java or Kotlin, then Retrofit is definitely worth a try.</p>



<h2 class="wp-block-heading" id="h-video-tutorial">Video Tutorial</h2>



<p>If you prefer <strong>video content</strong>, then check out my video:</p>



<div style="text-align: center; width: 90%; margin-left: 5%;">
<a href="https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FlT3-NBWV9HU%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /></p></div>



<p>If you find this content useful,<strong> please leave a subscription</strong> 🙂</p>



<h2 class="wp-block-heading" id="h-2-imports">2. Imports</h2>



<p>It&#8217;s worth mentioning, that Retrofit requires <strong>at minimum Java 8+ or Android API 21+</strong>, so it won&#8217;t be compatible with the legacy codebase.</p>



<p>Moreover, depending on when you are reading this article, the latest stable version can be different and I recommend using the latest one. In my examples, I will be using version: <strong>2.9.0</strong>.</p>



<h3 class="wp-block-heading" id="h-2-1-maven">2.1. Maven</h3>



<p>If you are working with Maven, then you can add it to your project with the following lines:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;dependency>
  &lt;groupId>com.squareup.retrofit2&lt;/groupId>
  &lt;artifactId>retrofit&lt;/artifactId>
  &lt;version>(VERSION)&lt;/version>
&lt;/dependency></pre>


<p>[elementor-template id=&#8221;9007393&#8243;]</p>



<h3 class="wp-block-heading" id="h-2-2-gradle">2.2. Gradle</h3>



<p>Alternatively, we can use Gradle to fetch the library:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// build.gradle
implementation 'com.squareup.retrofit2:retrofit:&lt;VERSION>'

// build.gradle.kts
implementation("com.squareup.retrofit2:retrofit:&lt;VERSION>")</pre>



<h3 class="wp-block-heading" id="h-2-3-serialization-amp-deserialization">2.3. Serialization &amp; Deserialization</h3>



<p>By default, Retrofit allows us to work only with <strong>OkHttp&#8217;s RequestBody</strong> and <strong>ResponseBody</strong> objects. Although sometimes it might be sufficient, in most cases we would like to make use of some serialization library when dealing with payloads.</p>



<p>Thankfully, we can achieve that pretty easily by importing desired Converter to our project:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/google/gson">Gson</a>: <em>com.squareup.retrofit2:converter-gson</em></li>



<li><a href="https://github.com/FasterXML/jackson">Jackson</a>: <em>com.squareup.retrofit2:converter-jackson</em></li>



<li><a href="https://github.com/square/moshi/">Moshi</a>: <em>com.squareup.retrofit2:converter-moshi</em></li>



<li><a href="https://developers.google.com/protocol-buffers/">Protobuf</a>: <em>com.squareup.retrofit2:converter-protobuf</em></li>



<li><a href="https://github.com/square/wire">Wire</a>: <em>com.squareup.retrofit2:converter-wire</em></li>



<li><a href="http://simple.sourceforge.net/">Simple XML</a>: <em>com.squareup.retrofit2:converter-simplexml</em></li>



<li><a href="https://docs.oracle.com/javase/tutorial/jaxb/intro/index.html">JAXB</a>: <em>com.squareup.retrofit2:converter-jaxb</em></li>



<li>Scalars: <em>com.squareup.retrofit2:converter-scalars</em></li>
</ul>



<p>For the purposes of this tutorial, I&#8217;ve picked the <strong>Jackson</strong> library, so we need to add the following to <strong>build.gradle.kts</strong> file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">implementation("com.squareup.retrofit2:converter-jackson:2.9.0")</pre>



<h2 class="wp-block-heading" id="h-3-retrofit-configuration-with-kotlin">3. Retrofit Configuration With Kotlin</h2>



<p>As the next step, let&#8217;s see how can we configure Retrofit to work with Kotlin.</p>



<h3 class="wp-block-heading" id="h-3-1-add-dto">3.1. Add DTO</h3>



<p>Firstly, let&#8217;s add an example user DTO to our project:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class User(
  @JsonProperty("id") val id: Long,
  @JsonProperty("name") val name: String,
  @JsonProperty("age") val age: Int
)</pre>



<p>As we can see, this simple class expects the JSON returned by the external API to be in the following format:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="json" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "id": 1,
  "name": "Name-1",
  "age": 21
}</pre>



<h3 class="wp-block-heading" id="h-3-2-implement-retrofitclient">3.2. Implement RetrofitClient</h3>



<p>Following, let&#8217;s add create a <strong>RetrofitClient</strong> object:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">object RetrofitClient {

  private const val BASE_URL = "http://localhost:8090/v1/"

  fun getClient(): Retrofit =
    Retrofit.Builder()
      .baseUrl(BASE_URL)
      .addConverterFactory(JacksonConverterFactory.create())
      .build()
}</pre>



<p>The above code is basically responsible for the following:</p>



<ul class="wp-block-list">
<li>setting the base URL for external API</li>



<li>registering converter factory for objects serialization and deserialization</li>



<li>creating Retrofit instance</li>
</ul>



<p>It&#8217;s worth mentioning that by default the <strong>OkHttpClient</strong> will be used underneath, as a factory for calls. Additionally we have to keep in mind that <strong>baseUrl has to end in /</strong>. Otherwise, the build will fail with <strong>IllegalArgumentException</strong>.</p>



<h3 class="wp-block-heading" id="h-3-3-add-okhttpclient-interceptor">3.3. Add OkHttpClient Interceptor</h3>



<p>As the next step let&#8217;s take a look on how to add interceptors to our requests.</p>



<p>If you are wondering why would we need it, then the answer is pretty simple. Oftentimes, when working with external APIs we want to perform some repeatable actions, like:</p>



<ul class="wp-block-list">
<li>adding authorization headers</li>



<li>logging</li>



<li>error handling etc.</li>
</ul>



<p>And to avoid repeating the same code across the whole app, we can simply add an interceptor, which will affect our calls.</p>



<p>With that being said, let&#8217;s implement a simple <strong>RequestInterceptor</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">object RequestInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    println("Outgoing request to ${request.url()}")
    return chain.proceed(request)
  }
}</pre>



<p>As we can see, the above code will print the information about outgoing requests URLs to the output. Later in the article, we will see how to add more interceptors.</p>



<p>But for now, let&#8217;s modify the <strong>RetrofitClient</strong> to make use of a new interceptor:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val okHttpClient = OkHttpClient()
  .newBuilder()
  .addInterceptor(RequestInterceptor)
  .build()

fun getClient(): Retrofit =
  Retrofit.Builder()
    .client(okHttpClient)
    .baseUrl(BASE_URL)
    .addConverterFactory(JacksonConverterFactory.create())
    .build()</pre>



<h2 class="wp-block-heading" id="h-4-handle-responses">4. Handle Responses</h2>



<p>As the next step, let&#8217;s see how to handle Retrofit responses in our Kotlin codebase.</p>



<p>Let&#8217;s start with adding the <strong>UserApi</strong> interface:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">interface UserApi {
  @GET("users")
  fun getUsers(): Call&lt;List&lt;User>>
}</pre>



<p>As can be seen, the above function will be used to perform <em>GET</em> requests to <em>http://localhost:8090/v1/users</em> endpoint. In the next chapter we will take a closer look at all supported HTTP methods, but for now, let&#8217;s discuss the <strong>Call interface</strong>.</p>



<p>A <strong>Call</strong> is basically an invocation of a Retrofit method that sends a request to a web server and returns a response. It can be used synchronously with the <strong>execute</strong> or asynchronously with <strong>enqueue</strong> methods. Additionally, each call can be cancelled at any time with <strong>cancel</strong>.</p>



<p>In this article, <strong>we will focus on synchronous calls</strong>. Nevertheless, if you would like to learn how to work with Retrofit and Kotlin coroutines, please let me know in the comments section. I will be more than happy to make a continuation for this topic.</p>



<h3 class="wp-block-heading" id="h-4-1-response-information">4.1. Response Information</h3>



<p>With that being said, let&#8217;s add a <strong>UserService</strong> and make use of our configuration:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class UserService {

  private val retrofit = RetrofitClient.getClient()
  private val userApi = retrofit.create(UserApi::class.java)

}</pre>



<p>Following, let&#8217;s see what information about the response can we obtain with Retrofit:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">fun successfulUsersResponse() {
  val usersResponse = userApi.getUsers()
    .execute()

  val successful = usersResponse.isSuccessful
  val httpStatusCode = usersResponse.code()
  val httpStatusMessage = usersResponse.message()

}</pre>



<p>Basically, the <strong>execute()</strong> method returns the <strong>Response&lt;T&gt;</strong>, which lets us obtain info about the&#8230; response 🙂</p>



<p>Let&#8217;s have a close look at each line:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val successful = usersResponse.isSuccessful</pre>



<p>The <strong>isSuccessful</strong> returns true, if the HTTP code is in the range <strong>[200&#8230;300]</strong>. It is a really good choice when we don&#8217;t care about the specific codes.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val httpStatusCode = usersResponse.code()</pre>



<p>On the other hand, the <strong>code()</strong> method returns the exact <strong>Integer value</strong> of the response HTTP status code.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val httpStatusMessage = usersResponse.message()</pre>



<p>Finally, the <strong>message()</strong>, might be useful, if we would like to get the HTTP status message, like <strong>OK</strong>.</p>



<h3 class="wp-block-heading" id="h-4-2-successful-response-body">4.2. Successful Response Body</h3>



<p>Following, let&#8217;s see how easily we can obtain the response body:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val body: List&lt;User>? = usersResponse.body()</pre>



<p>Nevertheless, please keep in mind that Retrofit <strong>body() method may return null</strong>, so we should handle it properly with Kotlin.</p>



<h3 class="wp-block-heading" id="h-4-3-retrofit-error-body">4.3. Retrofit Error Body</h3>



<p>Life would be much easier, if there were no errors.</p>



<p>Nevertheless, they happen, and it&#8217;s better to get more information about them:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val errorBody: ResponseBody? = usersResponse.errorBody()</pre>



<p>The rule is pretty simple here: when the response is <strong>successful</strong>, the <strong>body</strong> is populated. Oherwise, the <strong>errorBody</strong> field <strong>is not null</strong>. It&#8217;s worth mentioning here that Retrofit <strong>errorBody()</strong> method is not generic and we have to handle payload manually.</p>



<p>Let&#8217;s see how can we achieve that with Jackson library. Firstly, let&#8217;s add the <strong>ErrorResponse</strong> data class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data class ErrorResponse(
  @JsonProperty("message") val message: String
)</pre>



<p>Following, let&#8217;s use the <strong>ObjectMapper</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val errorBody: ResponseBody? = usersResponse.errorBody()

val mapper = ObjectMapper()

val mappedBody: ErrorResponse? = errorBody?.let { notNullErrorBody ->
  mapper.readValue(notNullErrorBody.toString(), ErrorResponse::class.java)
}</pre>



<p>This way, when <strong>Retrofit</strong> populates the <strong>errorBody</strong> property, we use Kotlin&#8217;s <strong>let</strong> function to deserialize payload into the <strong>ErrorResponse</strong> instance.</p>



<h3 class="wp-block-heading" id="h-4-4-read-response-headers">4.4. Read Response Headers</h3>



<p>Finally, let&#8217;s take a look at response headers, because sometimes they can contain useful information:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val headers = usersResponse.headers()
val customHeaderValue = headers["custom-header"]</pre>



<p>As we can see, with these two lines we can simply obtain the value of the <em>custom-header</em> returned from external API.</p>



<h2 class="wp-block-heading" id="h-5-http-methods">5. HTTP Methods</h2>



<p>So far, we&#8217;ve learned how to handle various responses, but <em>GET</em> is not the only option, so let&#8217;s have a look at other possibilities.</p>



<p>Basically, Retrofit comes with 8 built-in annotations: <strong>HTTP, GET, POST, PUT, PATCH, DELETE, OPTIONS</strong> and <strong>HEAD</strong>. Although the choice will depend on the endpoint we query, I would like to take a closer look at <strong>@HEAD </strong>and <strong>@HTTP</strong> annotations.</p>



<h3 class="wp-block-heading" id="h-5-1-retrofit-head">5.1. Retrofit @HEAD</h3>



<p>Let&#8217;s start with the <strong>@HEAD</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@HEAD("users")
fun headUsers(): Call&lt;Void></pre>



<p>As we can see, the return type here is <strong>Void</strong>&#8211; and it must be always be. Otherwise, <strong>Retrofit will throw IllegalArgumentException with: HEAD method must use Void as response type message</strong>.</p>



<h3 class="wp-block-heading" id="h-5-2-retrofit-http-and-delete">5.2. Retrofit @HTTP and @DELETE</h3>



<p>The <strong>@HTTP</strong> annotation is pretty interesting, as well. It lets us use a custom HTTP verb for a request.</p>



<p>Let&#8217;s see an example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users")
fun getUsers(): Call&lt;List&lt;User>>

@HTTP(method = "GET", path = "users")
fun httpUsers(): Call&lt;List&lt;User>></pre>



<p>Basically, both functions work exactly the same and in real-life scenarios we will hardly ever use the second option. Given that, why should we care about it?</p>



<p>Well, let&#8217;s see the following snippet:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@DELETE("users")
fun failingDeleteUser(@Body user: User): Call&lt;User></pre>



<p>As the name of the function suggests, it will fail. And to be more specific, it will fail with the following message: <strong>Non-body HTTP method cannot contain @Body</strong>.</p>



<p>In such a case, the <strong>@HTTP</strong> annotation allows us to set <strong>hasBody</strong> flag, which we can use to perform the <strong>DELETE</strong> request with payload:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@HTTP(method = "DELETE", path = "users", hasBody = true)
fun workingDeleteUser(@Body user: User): Call&lt;User></pre>



<h2 class="wp-block-heading" id="h-6-url-manipulation">6. URL Manipulation</h2>



<p>Until now, we saw how to use a hard-coded URLs and sometimes it will be sufficient. Nevertheless, in real-life scenarios we will have to specify additional <strong>query parameters</strong>, or <strong>path variables</strong> sooner or later.</p>



<h3 class="wp-block-heading" id="h-6-1-use-absolute-path">6.1. Use Absolute Path</h3>



<p>As the first step, let&#8217;s see how can we instruct Retrofit to use a custom, <strong>absolute path</strong> in our Kotlin interface:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("http://localhost:8090/v3/users")
fun getUsersV3(): Call&lt;List&lt;User>></pre>



<p>This might be really helpful, when we would like to query another API, or just another version of the same provider without the need to set up next interface. Just like above handler will perform a <strong>GET</strong> request to <strong>V3</strong> endpoint.</p>



<h3 class="wp-block-heading" id="h-6-2-dynamic-url-with-url">6.2. Dynamic URL With @Url</h3>



<p>On the other hand, Retrofit has the possibility to specify the URL on method invocation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET
fun getUsersDynamic(@Url url: String): Call&lt;List&lt;User>></pre>



<p>This way, we have the possibility to specify desired URL as an argument. Nevertheles, it&#8217;s a good time to have a look on how URLs are resolved in Retrofit:</p>



<ul class="wp-block-list">
<li><strong>userApi.getUsersDynamic(&#8220;users&#8221;)</strong> &#8211; will be resolved to <em>http://localhost:8090/v1/users</em></li>



<li><strong>userApi.getUsersDynamic(&#8220;/users&#8221;)</strong> &#8211; will be treated as <em>http://localhost:8090/users</em></li>



<li><strong>userApi.getUsersDynamic(&#8220;http://localhost:8090/v3/users&#8221;)</strong> &#8211; just like in the previous example, will use the provided, absolute path</li>
</ul>



<h3 class="wp-block-heading" id="h-6-3-use-path-variable">6.3. Use Path Variable</h3>



<p>Following, let&#8217;s see how to make use of replacement blocks:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users/{userId}")
fun getUserById(@Path("userId") userId: Int): Call&lt;User></pre>



<p>As we can see, we can specify the user id when invoking the function. So the following call: <strong>userApi.getUserById(99)</strong>, will result in <strong>GET</strong> request to <strong>http://localhost:8090/v1/users/99</strong>.</p>



<h3 class="wp-block-heading" id="h-6-4-add-query-parameters">6.4. Add Query Parameters</h3>



<p>Another common way of exchanging information are query parameters:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users?sort_order=asc")
fun getUsersStaticQueryParam(): Call&lt;List&lt;User>></pre>



<p>As can be seen, we use a static <strong>sort_order</strong> query parameter. Although I discourage this approach I wanted to show that it is possible when working with Retrofit.</p>



<p>To get a better control over the sent parameters, we can use a <strong>@Query annotation</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users")
fun getUsersDynamicQueryParam(@Query("sort_order") order: String): Call&lt;List&lt;User>></pre>



<p>This way, our function becomes much more generic. Calling it with the <strong>&#8220;desc&#8221;</strong> argument, will result in <strong>sort_order=desc</strong> in our URL.</p>



<p>As the last one, let&#8217;s see how can we add multiple parameters with <strong>@QueryMap</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users")
fun getUsersDynamicQueryMap(@QueryMap parameters: Map&lt;String, String>): Call&lt;List&lt;User>></pre>



<p>This way, when the API requires multiple query parameters, we can encapsulate them in a map. Without that we would end up with a function taking plenty of arguments, which would affect code readability.</p>



<p>So, the following code:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">userApi.getUsersDynamicQueryMap(
  mapOf(
    "order" to "asc",
    "name" to "some"
  )
)</pre>



<p>Will be translated to: <strong>http://localhost:8090/v1/users?order=asc&amp;name=some</strong></p>



<h2 class="wp-block-heading" id="h-7-request-headers">7. Request Headers</h2>



<p>Headers are inseparable part of every REST communication. Oftentimes, we will have to send additional information, like <strong>Content-Type</strong>, or <strong>Authorization</strong>. In this chapter we will learn a few possibilities Retrofit gives us to work with them.</p>



<h3 class="wp-block-heading" id="h-7-1-static-headers">7.1. Static Headers</h3>



<p>Let&#8217;s start with a <strong>single header</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Headers("User-Agent: codersee-application")
@GET("users")
fun getUsersSingleStaticHeader(): Call&lt;List&lt;User>></pre>



<p>Similarly, we can append <strong>multiple headers</strong> to the request:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Headers(
  value = [
    "User-Agent: codersee-application",
    "Custom-Header: my-custom-header"
])
@GET("users")
fun getUsersMultipleStaticHeaders(): Call&lt;List&lt;User>></pre>



<h3 class="wp-block-heading" id="h-7-2-dynamic-headers">7.2. Dynamic Headers</h3>



<p>Although the two above will be useful in some cases, oftentimes we will need to pass a dynamic value for a header, like Authorization for instance. To achieve that, we can use a <strong>@Header</strong> annotation:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users")
fun getUsersDynamicHeader(@Header("Authorization") token: String): Call&lt;List&lt;User>></pre>



<p>Just like with <strong>@Query</strong> annotation, Retrofit allows us to pass multiple headers in a Map form <strong>with @HeaderMap</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@GET("users")
fun getUsersHeaderMap(@HeaderMap headers: Map&lt;String, String>): Call&lt;List&lt;User>></pre>



<h3 class="wp-block-heading" id="h-7-3-authorization-interceptor">7.3. Authorization Interceptor</h3>



<p>As the next step, I would like to show you how to make life easier and extract logic responsible for tokens generation to Retrofit config. This is way, each request to the given API will contain a generated token and we won&#8217;t need to add it each time.</p>



<p>Let&#8217;s start with adding a Kotlin object called <strong>AuthorizationInterceptor</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">object AuthorizationInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
    val requestWithHeader = chain.request()
      .newBuilder()
      .header(
        "Authorization", UUID.randomUUID().toString()
      ).build()
    return chain.proceed(requestWithHeader)
  }
}</pre>



<p>Just like in the chapter <strong>number 3</strong>, we extend the <strong>Interceptor</strong> interface, but this time we additionally call a <strong>newBuilder()</strong> on the request instance. With that being done, we can modify its behavior, like add headers or tags (and I highly encourage you to check all the possible options). In your project, the <strong>UUID.randomUUID().toString()</strong> would be replaced with a call to another service, or logic responsible for generating real tokens.</p>



<p>As the last step, we have to add it to the <strong>OkHttpClient</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val okHttpClient = OkHttpClient()
  .newBuilder()
  .addInterceptor(AuthorizationInterceptor)
  .addInterceptor(RequestInterceptor)
  .build()</pre>



<p>This way, each request will be enhanced with the <strong>Authorization</strong> header.</p>



<h2 class="wp-block-heading" id="h-8-request-body">8. Request Body</h2>



<p>Finally, we can learn how to attach a payload to Retrofit requests.</p>



<h3 class="wp-block-heading" id="h-8-1-send-object-as-json">8.1. Send Object as JSON</h3>



<p>Let&#8217;s start with the most popular way of sending data- a JSON payload:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@POST("users")
fun postUsersWithPayload(@Body user: User): Call&lt;User></pre>



<p>With the <strong>@Body</strong> annotation, we can pass a User instance, which will be then <strong>serialized using configured Retrofit converter (Jackson in our case)</strong>.</p>



<h3 class="wp-block-heading" id="h-8-2-retrofit-url-encoded-form">8.2. Retrofit URL-Encoded Form</h3>



<p>On the other hand, if we would like to send data in a URL-Encoded Form, we can use the <strong>@FormUrlEncoded </strong>along with <strong>@Field</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@FormUrlEncoded
@POST("users")
fun postUsersFormUrlEncoded(@Field("field_one") fieldOne: String): Call&lt;User></pre>



<h3 class="wp-block-heading" id="h-8-3-multipart">8.3. Multipart</h3>



<p>Lastly, to send the data as a HTTP multipart request, we can use <strong>@Multipart</strong> on a function with <strong>@Part</strong> on each part send to the external REST API:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Multipart
@POST("users")
fun postUsersMultipart(@Part("something") partOne: RequestBody): Call&lt;User></pre>



<h2 class="wp-block-heading" id="h-9-retrofit-with-kotlin-summary">9. Retrofit With Kotlin Summary</h2>



<p>And that would be all for this article on Retrofit with Kotlin. We&#8217;ve learned together almost everything you will need to know when working on your very own project. As always, you can find the source code in this <a href="https://github.com/codersee-blog/kotlin-retrofit-2" target="_blank" rel="noopener">GitHub Repository</a>.</p>



<p>If you would like to learn a bit more, then check out the continuation of this article, in which I show how to use <a href="https://blog.codersee.com/retrofit-with-kotlin-coroutines-what-you-need-to-know/">Retrofit 2 with Kotlin Coroutines.</a> On the other hand, if you would like to combine this knowledge and learn how to create back-end services with Kotlin, you will find step-by-step tutorials in the <a href="https://blog.codersee.com/category/ktor/">Ktor category</a>.</p>



<p>I hope you enjoyed this article and will be really happy if you would like to give me feedback in the comments section.</p>
<p>The post <a href="https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/">Retrofit With Kotlin- The Ultimate Guide</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/retrofit-with-kotlin-the-ultimate-guide/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: blog.codersee.com @ 2026-05-14 12:42:06 by W3 Total Cache
-->