1

I am trying to use Jackson to serialize the same DTO object in 2 different ways, depending on the @JsonView.

I want to use 2 different names for the same field. In one case I want to name the json property myField (just like the class field name), in the other I want it to be named myInternalApiField.

As a result I would like to see outcomes similar to the presented below:

Usage 1 (External API View):

{
    "myField": "value1",
    "myOtherField": "otherValue"
}

Usage 2 (Internal API View):

{
    "myInternalApiField": "value1",
    "myOtherField": "otherValue"
}

In my implementation in Java to achieve that I used the combination of custom getters, setters and @JsonView annotation as below:

public class CustomDTO {
        @JsonView(Views.ExternalApiView)
        private String myField;
        // Other fields here

        @JsonView(Views.InternalApiView)
        public String getMyInternalApiField() { return myField; }
        @JsonView(Views.InternalApiView)
        public void setMyInternalApiField(String value) { this.myField = value; }

        @JsonView(Views.ExternalApiView)
        public String getMyField() { return myField; }

        @JsonView(Views.ExternalApiView)
        public void setMyField(String value) { this.myField = value }
}

However I don't know how to properly achieve the same result in Kotlin.

I was thinking about using something like:

data class CustomDTO(
        @get:[JsonView(Views.ExternalApiView) JsonProperty("myField")]
        @get:[JsonView(Views.InternalApiView) JsonProperty("myInternalApiField")]
        @set:[JsonView(Views.InternalApiView) JsonProperty("myField")]
        @set:[JsonView(Views.InternalApiView) JsonProperty("myInternalApiField")]
        var myField: String,
        val myOtherField: String,
        val myDifferentField: String
)

But this is not allowed in Kotlin.

Do you have any suggestions how to utilize the @JsonView in Kotlin in the similar way as I did it in Java?

Rozart
  • 1,668
  • 14
  • 27

1 Answers1

1

How about something like:

data class CustomDTO(
        @JsonView(ExternalApiView::class)
        var myField: String,
        val myOtherField: String,
        val myDifferentField: String
) {
    val myExternalField: String
        @JsonView(InternalApiView::class)
        get() {
            return myField
        }
}

It looks like there are ways that don't require creating computed properties in the DTO, like:

But these have their own complexity, even if that complexity isn't in the DTO class. I'm not sure these are much more appealing to me but you could see if they appeal to you.

Geoffrey Wiseman
  • 5,459
  • 3
  • 34
  • 52
  • This seems to be a working solution, but won't it result in a new field in the CustomDTO class, visible also outside of the serialization/deserialization process? I am trying no to introduce new variables ;) – Rozart Dec 08 '18 at 17:29
  • 1
    I don't think it's introducing more variables any more than the Java version you posted would -- the `val` in the kotlin version above is a derived value, there's no additional storage. It would be visible outside the serialization process, but so would `getMyInternalApiField` in the Java version, wouldn't it? – Geoffrey Wiseman Dec 10 '18 at 20:57
  • You have convinced me! Let me just wait a bit to see if any other suggested solutions are going to show up here and then I will accept your answer. Thank you a lot! – Rozart Dec 11 '18 at 08:50
  • 1
    I do agree that it would be nice if there were a way to do this with annotations alone, although I don't know of a way to do it. ;) – Geoffrey Wiseman Dec 11 '18 at 21:48