Reputation: 2045
I'm trying to start using Kotlin in my existing Java project, but Jackson is not detecting the @JsonProperty in my Kotlin objects (whereas it works perfectly with Java objects).
Any way to configure Jackson to make this work for Kotlin like it works for Java?
Here is the Java class:
public class TestJavaObj {
@JsonProperty
private String includeMe;
private String dontIncludeMe;
public TestJavaObj(String includeMe, String dontIncludeMe) {
this.includeMe = includeMe;
this.dontIncludeMe = dontIncludeMe;
}
}
and the Kotlin class:
class TestKotlinObj(
@JsonProperty val includeMe: String,
val dontIncludeMe : String?
)
Here is the test code:
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper()
.registerModule(new KotlinModule()) //jackson-module-kotlin
.configure(MapperFeature.AUTO_DETECT_GETTERS, false)
.configure(MapperFeature.AUTO_DETECT_CREATORS, false)
.configure(MapperFeature.AUTO_DETECT_FIELDS, false)
.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false)
.configure(MapperFeature.AUTO_DETECT_SETTERS, false);
TestJavaObj javaObj = new TestJavaObj("hello", "world");
TestKotlinObj kotlinObj = new TestKotlinObj("hello", "world");
System.out.println("Expected: " + mapper.writeValueAsString(javaObj));
System.out.println("Got: " + mapper.writeValueAsString(kotlinObj));
}
And here is the output:
Expected: {"includeMe":"hello"}
Got: {}
Version numbers from my gradle file:
kotlin_version = '1.3.72'
...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
...
apply plugin: 'kotlin'
...
compile('com.fasterxml.jackson.core:jackson-annotations:2.10.3')
compile('com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
Upvotes: 2
Views: 1973
Reputation: 8307
Specify annotation use-site target:
class TestKotlinObj(
@get:JsonProperty val includeMe: String,
val dontIncludeMe : String
)
Result:
Expected: {"includeMe":"hello"}
Got: {"includeMe":"hello"}
Background:
The class translated to Java bytecode has only a constructor parameter annotated:
public final class TestKotlinObj {
@NotNull // no annotation here
private final String includeMe;
@NotNull
private final String dontIncludeMe;
@NotNull // nor here
public final String getIncludeMe() {
return this.includeMe;
}
@NotNull
public final String getDontIncludeMe() {
return this.dontIncludeMe;
}
// but here
// vvvv
public TestKotlinObj(@JsonProperty @NotNull String includeMe, @NotNull String dontIncludeMe) {
Intrinsics.checkParameterIsNotNull(includeMe, "includeMe");
Intrinsics.checkParameterIsNotNull(dontIncludeMe, "dontIncludeMe");
super();
this.includeMe = includeMe;
this.dontIncludeMe = dontIncludeMe;
}
}
Which is not taken into account when serializing the object.
See related issue:
Kotlin data class Jackson @JsonProperty
not honored
Upvotes: 3
Reputation: 2166
Try changing the Kotlin class to this:
class TestKotlinObj {
@JsonProperty
val includeMe: String;
val dontIncludeMe : String;
constructor(includeMe: String, dontIncludeMe: String) {
this.includeMe = includeMe;
this.dontIncludeMe = dontIncludeMe;
}
}
It may be that the current Kotlin class you have is equivalent to this in java (which would obviously not work):
public class TestJavaObj {
public String includeMe;
public String dontIncludeMe;
public TestJavaObj(@JsonProperty String includeMe, String dontIncludeMe) {
this.includeMe = includeMe;
this.dontIncludeMe = dontIncludeMe;
}
}
Upvotes: 1