РЕДАКТИРОВАТЬ : вот, в сообщении в блоге разработчиков Джексона, кажется, что 2.12 может увидеть улучшения в отношении внедрения конструктора. (Текущая версия на момент редактирования - 2.11.1)
Улучшение автоматического обнаружения создателей конструкторов, включая решение / смягчение проблем с неоднозначными конструкторами с одним аргументом (делегирование по сравнению со свойствами)
Это все еще верно для базы данных Джексона 2.7.0.
Джексон @JsonCreator
аннотации 2,5 Javadoc или Джексон аннотаций документации грамматик ( конструктор s и завод метод s ) Пусть считает , что на самом деле можно отметить несколько конструкторов.
Аннотации маркеров, которые можно использовать для определения конструкторов и фабричных методов как одного, чтобы использовать для создания новых экземпляров связанного класса.
Глядя на код, в котором указаны создатели , похоже, что Джексон CreatorCollector
игнорирует перегруженные конструкторы, поскольку проверяет только первый аргумент конструктора .
Class<?> oldType = oldOne.getRawParameterType(0);
Class<?> newType = newOne.getRawParameterType(0);
if (oldType == newType) {
throw new IllegalArgumentException("Conflicting "+TYPE_DESCS[typeIndex]
+" creators: already had explicitly marked "+oldOne+", encountered "+newOne);
}
oldOne
является первым идентифицированным создателем конструктора.
newOne
является создателем перегруженного конструктора.
Значит, такой код работать не будет.
@JsonCreator
public Phone(@JsonProperty("value") String value) {
this.value = value;
this.country = "";
}
@JsonCreator
public Phone(@JsonProperty("country") String country, @JsonProperty("value") String value) {
this.value = value;
this.country = country;
}
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
Но этот код будет работать:
@JsonCreator
public Phone(@JsonProperty("value") String value) {
this.value = value;
enabled = true;
}
@JsonCreator
public Phone(@JsonProperty("enabled") Boolean enabled, @JsonProperty("value") String value) {
this.value = value;
this.enabled = enabled;
}
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
Это немного взломано и не может быть надежным в будущем .
Документация нечетко описывает, как работает создание объекта; однако из того, что я понял из кода, можно смешивать разные методы:
Например, можно иметь статический фабричный метод, аннотированный @JsonCreator
@JsonCreator
public Phone(@JsonProperty("value") String value) {
this.value = value;
enabled = true;
}
@JsonCreator
public Phone(@JsonProperty("enabled") Boolean enabled, @JsonProperty("value") String value) {
this.value = value;
this.enabled = enabled;
}
@JsonCreator
public static Phone toPhone(String value) {
return new Phone(value);
}
assertThat(new ObjectMapper().readValue("\"+336\"", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
Это работает, но не идеально. В конце концов, это может иметь смысл, например, если JSON такой динамический тогда, возможно, следует использовать конструктор делегата для обработки вариантов полезной нагрузки гораздо более элегантно, чем с несколькими аннотированными конструкторами.
Также обратите внимание, что Джексон упорядочивает создателей по приоритету , например, в этом коде:
@JsonCreator
public Phone(@JsonProperty("value") String value) {
this.value = value;
}
@JsonCreator
public Phone(Map<String, Object> properties) {
value = (String) properties.get("value");
}
assertThat(new ObjectMapper().readValue("\"+336\"", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\"}", Phone.class).value).isEqualTo("+336");
assertThat(new ObjectMapper().readValue("{\"value\":\"+336\",\"enabled\":true}", Phone.class).value).isEqualTo("+336");
На этот раз Джексон не вызовет ошибку, но Джексон будет использовать только конструктор делегатаPhone(Map<String, Object> properties)
, что означает, что Phone(@JsonProperty("value") String value)
никогда не используется.