@JsonProperty vs @JsonAlias in Jackson

This time, I would like to show you a @JsonProperty vs @JsonAlias Jackson annotation comparison and a few things worth remembering.
This image featured image for @JsonProperty vs @JsonAlias in Jackson article shows shows Codersee logo and people sitting together in the background.

1. Introduction

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

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’re gonna learn today can be easily incorporated into Java projects, as well.

3. Serialization vs Deserialization

Nevertheless, before we dive into the @JsonProperty vs @JsonAlias topic, let’s take a second to distinguish these two terms:

  • serialization– 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
  • deserialization– this is the reverse process, in which a stream of bytes (ex. JSON) is converted to an object existing in memory

Make a real progress thanks to practical examples, exercises, and quizzes.

Image presents a Kotlin Course box mockup for "Kotlin Handbook. Learn Through Practice"

2. @JsonProperty

2.1. Definition And Defaults

With that being said, let’s answer the question- what exactly the @JsonProperty annotation is?

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’s ObjectMapper to map a given JSON field to a particular object field.

By default, the field name is used as a property name:

data class ExampleDto(
    @JsonProperty val id: Long,
    @JsonProperty val name: String
)

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:

{
  "id": 1,
  "name": "Piotr"
}

Of course, the above structure will be the same for both serialization and deserialization.

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

2.2. So What Do I Need @JsonProperty For?

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

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:

data class ExampleDto(
    @JsonProperty val id: Long,
    @JsonProperty("person_name") val personName: String
)

And this time, the JSON structure will look, as follows:

{
  "id": 1,
  "person_name": "Piotr"
}

This way, a camel case used in our code is translated to the snake case, often used in REST APIs.

2.3. Different Structure For Serialization And Deserialization

As the next step, let’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.

Let’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:

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
)

As can be seen, we made use of the @get, which in Kotlin means that we want to apply the annotation to property getter.

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

{
  "external_id": 1,
  "external_name": "Piotr"
}

And forward it to the user in this form:

{
  "id_for_user": 1,
  "name_for_user": "Piotr"
}

2.4. @JsonProperty With Enums

Another interesting feature of @JsonProperty is the possibility to use it with enums. However, it’s been added in Jackson 2.6, so you might want to check a version in your project.

Anyway, let’s see the example:

enum class SomeType {
  STANDARD, PREMIUM
}

data class ExampleDto(
  val id: Long,
  val name: String,
  val type: SomeType
)

With the above code, our objects will look, as follows:

{
  "id": 1,
  "name": "Piotr",
  "type": "PREMIUM"
}

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

enum class SomeType {
  @JsonProperty("Tier 1")
  STANDARD,
  @JsonProperty("Tier 2")
  PREMIUM
}

After this change, the provided value will be used:

{
  "id": 1,
  "name": "Piotr",
  "type": "Tier 2"
}

This strategy can be useful when we don’t necessarily want to show the implementation details to users.

2.4. Different Access Types

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

@JsonProperty lets us set an optional access property to change the way Jackson interprets visibility rules for a given field. Let’s have a look at each one of the 4 access types:

  • AUTO (default) – which means that visibility rules will be applied to determine a read/write access of the property.

As always, let’s have a look at the example:

data class ExampleDto(
  @JsonProperty val id: Long,
  @JsonProperty val name: String,
  @JsonProperty private val email: String
)

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

{
  "id": 1,
  "name": "Piotr"
}

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

  • READ_WRITE – this means that property will be accessible for both serialization and deserialization regardless of the visibility rules.

Let’s apply a small change to our DTO:

data class ExampleDto(
  @JsonProperty val id: Long,
  @JsonProperty val name: String,
  @JsonProperty(access = JsonProperty.Access.READ_WRITE) private val email: String
)

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

{
  "id": 1,
  "name": "Piotr",
  "email": "contact@codersee.com"
}
  • READ_ONLY – when applied, a property can be read for serialization, but cannot be set during the deserialization.

With that being said, let’s see another example:

data class ExampleDto(
  @JsonProperty(access = JsonProperty.Access.READ_ONLY) val id: Long?,
  @JsonProperty val name: String
)

As can be seen, the id property has to be set as a nullable type, so that it won’t fail during the deserialization. The serialized object looks as follows:

{
  "id": 1,
  "name": "Piotr"
}

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.

  • WRITE_ONLY – with this one, the property can be set during the deserialization, but cannot be set during the serialization.

And again, let’s see it in action:

data class ExampleDto(
  @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) val id: Long,
  @JsonProperty val name: String
)

This time, the serialized object will have the following form:

{
  "name": "Piotr"
}

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

3. @JsonAlias

With all of the above being said, let’s finally see what exactly @JsonAlias is? Since Jackson 2.9, this annotation lets us specify one, or more alternative names accepted during the deserialization.

So, for a given example:

data class ExampleDto(
  val id: Long,
  @JsonAlias("n", "N", "surname")
  val name: String
)

The name value can be set from either n, N, name, or surname property.

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

{
  "id": 1,
  "surname": "Piotr",
  "N": "John"
}

Then, the answer is- the last one.

Moreover, it can be used with enums, as well.

4. @JsonProperty vs @JsonAlias

Finally, let’s get back to the title of this post, the @JsonProperty vs @JsonAlias comparison.

Well, the most important thing to remember is that the @JsonAlias affects the deserialization process only. 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).

In my opinion, this annotation is a great addition to the @JsonProperty but should be used wisely. We don’t want any unwanted value to be set for our property 🙂

5. Summary

And that would be all for this article on @JsonProperty vs @JsonAlias. If you’d like to learn a bit more or check out other annotations, then please refer to the Jackson documentation.

Let me know what are your favorite Jackson annotations. As always, you can do it in the comment section below, or by the contact form.

Finally, if you would like to contribute to Codersee and support the creation of content, you can “buy me a coffee” right here. Have a great day!

Share this:

Related content

Newsletter
Image presents 3 ebooks with Java, Spring and Kotlin interview questions.

Never miss any important updates from the Kotlin world and get 3 ebooks!

You may opt out any time. Terms of Use and Privacy Policy