Конечно, и это довольно просто.
Просто добавьте @JsonCreator
в конструктор.
class MyValueObject {
private String value;
@JsonCreator
public MyValueObject(String value) { this.value = value; }
@JsonValue
public String getValue() { return value; }
}
Или для Котлина вы бы, наверное,
data class MyValueObject @JsonCreator constructor(@JsonValue val value: String)
Когда вы используете @JsonCreator
без с префиксом параметра конструктора с
@JsonProperty("fieldName")
вы говорите Джексону передать всю строку JSON, которая в вашем случае является просто «примитивным» значением.
Очевидно, что Котлину не нравятся автоматически генерируемые пары геттер / сеттер.
Это работает, например,
class MyValueObject @JsonCreator constructor(private val value: String) {
@JsonValue
fun getValue() = value
}
Кроме того, после небольшой отладки я обнаружил, что проблема возникает здесь
@Override
public Boolean hasAsValue(Annotated a) {
JsonValue ann = _findAnnotation(a, JsonValue.class);
if (ann == null) {
return null;
}
return ann.value();
}
В JacksonAnnotationIntrospector
.
Я не знаю почему, но Джексон все еще ищет аннотацию @JsonValue
в общедоступном поле или в общедоступном геттере. Котлин помещает аннотацию в приватное поле, поэтому Джексон не может ее найти.
Решение
data class MyValueObject @JsonCreator constructor(@JvmField @JsonValue val value: String)
или даже лучше
data class MyValueObject @JsonCreator constructor(@get:JsonValue val value: String)
Как писал Марк фон Рентельн в комментариях, вы также можете опустить @JsonCreator
data class MyValueObject(@get:JsonValue val value: String)
Что кажется недокументированным, однако. Если кто-то может указать, где описывается это поведение, это было бы здорово!